- 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:
parent
238d4c3fac
commit
ea8c94d637
24 changed files with 367 additions and 160 deletions
106
src/p_map.cpp
106
src/p_map.cpp
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue