- Fixed: Argument count for UsePuzzleItem was wrong.

- Added more things from Gez's experimental build:
  * MBF grenade and bouncing code.
  * Arch Vile ghosts emulation (only for compatibility.txt.)
  * Several MBF related compatibility options.



SVN r1821 (trunk)
This commit is contained in:
Christoph Oelckers 2009-09-14 20:47:53 +00:00
commit ea8c94d637
24 changed files with 367 additions and 160 deletions

View file

@ -590,17 +590,25 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
return false;
}
if (!(tm.thing->flags & MF_MISSILE) || (ld->flags & (ML_BLOCKEVERYTHING|ML_BLOCKPROJECTILE)))
{
// MBF bouncers are treated as missiles here.
bool Projectile = (tm.thing->flags & MF_MISSILE || tm.thing->BounceFlags & BOUNCE_MBF);
// MBF considers that friendly monsters are not blocked by monster-blocking lines.
// This is added here as a compatibility option. Note that monsters that are dehacked
// into being friendly with the MBF flag automatically gain MF3_NOBLOCKMONST, so this
// just optionally generalizes the behavior to other friendly monsters.
bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST)
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING|ML_BLOCKPROJECTILE))) {
if (ld->flags & ML_RAILING)
{
rail = true;
}
else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(tm.thing->flags3 & MF3_NOBLOCKMONST) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((tm.thing->flags & MF_MISSILE) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
((ld->flags & ML_BLOCK_FLOATERS) && (tm.thing->flags & MF_FLOAT))) // block floaters
else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
{
if (tm.thing->flags2 & MF2_BLASTED)
{
@ -754,6 +762,13 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
bool solid;
int damage;
if (!((thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY))
return true; // can't hit thing
fixed_t blockdist = thing->radius + tm.thing->radius;
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
return true;
// don't clip against self
if (thing == tm.thing)
return true;
@ -764,13 +779,6 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->GetSpecies() == thing->GetSpecies()))
return true;
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
return true; // can't hit thing
fixed_t blockdist = thing->radius + tm.thing->radius;
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
return true;
tm.thing->BlockingMobj = thing;
topz = thing->z + thing->height;
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
@ -806,6 +814,26 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
return true;
}
}
// touchy object is alive, toucher is solid
if (thing->flags6 & MF6_TOUCHY && tm.thing->flags & MF_SOLID && thing->health > 0 &&
// Thing is an armed mine or a sentient thing
(thing->flags6 & MF6_ARMED || thing->IsSentient()) &&
// either different classes or players
(thing->player || thing->GetClass() != tm.thing->GetClass()) &&
// or different species if DONTHARMSPECIES
(!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) &&
// touches vertically
thing->z + thing->height >= tm.thing->z && tm.thing->z + tm.thing->height >= thing->z &&
// prevents lost souls from exploding when fired by pain elementals
(thing->master != tm.thing && tm.thing->master != thing))
// Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species
// but different classes trigger the touchiness, but that seems less straightforwards.
{
thing->flags6 &= ~MF6_ARMED; // Disarm
P_DamageMobj (thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object
return true;
}
// Check for skulls slamming into things
if (tm.thing->flags & MF_SKULLFLY)
{
@ -839,8 +867,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
LineSpecials[thing->special] (NULL, tm.thing, false, thing->args[0],
thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
}
// Check for missile
if (tm.thing->flags & MF_MISSILE)
// Check for missile or non-solid MBF bouncer
if (tm.thing->flags & MF_MISSILE || ((tm.thing->BounceFlags & BOUNCE_MBF) && !(tm.thing->flags & MF_SOLID)))
{
// Check for a non-shootable mobj
if (thing->flags2 & MF2_NONSHOOTABLE)
@ -891,7 +919,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
// [RH] What is the point of this check, again? In Hexen, it is unconditional,
// but here we only do it if the missile's damage is 0.
if ((tm.thing->BounceFlags & BOUNCE_Actors) && tm.thing->Damage == 0)
// MBF bouncer might have a non-0 damage value, but they must not deal damage on impact either.
if ((tm.thing->BounceFlags & BOUNCE_Actors) && (tm.thing->Damage == 0 || !(tm.thing->flags & MF_MISSILE)))
{
return (tm.thing->target == thing || !(thing->flags & MF_SOLID));
}
@ -1707,6 +1736,12 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
oldAboveFakeCeiling = eyez > oldsec->heightsec->ceilingplane.ZatPoint (thing->x, thing->y);
}
// Borrowed from MBF:
if (thing->BounceFlags & BOUNCE_MBF && // killough 8/13/98
!(thing->flags & (MF_MISSILE|MF_NOGRAVITY)) &&
!thing->IsSentient() && tm.floorz - thing->z > 16*FRACUNIT)
return false; // too big a step up for MBF bouncers under gravity
// the move is ok, so link the thing into its new position
thing->UnlinkFromWorld ();
@ -1973,8 +2008,6 @@ struct FSlide
bool BounceWall (AActor *mo);
};
//
// P_HitSlideLine
// Adjusts the xmove / ymove
@ -2153,7 +2186,8 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_
{
goto isblocking;
}
if (li->flags & ML_BLOCKMONSTERS && !(slidemo->flags3 & MF3_NOBLOCKMONST))
if (li->flags & ML_BLOCKMONSTERS && !((slidemo->flags3 & MF3_NOBLOCKMONST)
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY))))
{
goto isblocking;
}
@ -2596,7 +2630,10 @@ bool FSlide::BounceWall (AActor *mo)
// The amount of bounces is limited
if (mo->bouncecount>0 && --mo->bouncecount==0)
{
P_ExplodeMissile(mo, NULL, NULL);
if (mo->flags & MF_MISSILE)
P_ExplodeMissile(mo, NULL, NULL);
else
mo->Die(NULL, NULL);
return true;
}
@ -2637,7 +2674,28 @@ bool P_BounceWall (AActor *mo)
return slide.BounceWall(mo);
}
extern FRandom pr_bounce ("Bounce");
bool P_BounceActor (AActor *mo, AActor * BlockingMobj)
{
if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors)
|| ((mo->flags & MF_MISSILE) && (BlockingMobj->flags2 & MF2_REFLECTIVE)
|| ((!BlockingMobj->player) && (!(BlockingMobj->flags3 & MF3_ISMONSTER))))
))
{
fixed_t speed;
angle_t angle = R_PointToAngle2 (BlockingMobj->x,
BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce()%16)-8);
speed = P_AproxDistance (mo->velx, mo->vely);
speed = FixedMul (speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
mo->angle = angle;
angle >>= ANGLETOFINESHIFT;
mo->velx = FixedMul (speed, finecosine[angle]);
mo->vely = FixedMul (speed, finesine[angle]);
mo->PlayBounceSound(true);
return true;
}
else return false;
}
//============================================================================
//
@ -3976,7 +4034,9 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
while ((thing = it.Next()))
{
if (!(thing->flags & MF_SHOOTABLE) )
// Vulnerable actors can be damaged by radius attacks even if not shootable
// Used to emulate MBF's vulnerability of non-missile bouncers to explosions.
if (!((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE)))
continue;
// Boss spider and cyborg and Heretic's ep >= 2 bosses