- Eliminated all use of global variables used as output for P_CheckPosition

and P_TryMove. Moved BlockingLine and BlockingMobj into AActor because 
  the global variables can be easily overwritten with certain DECORATE 
  constructs.


SVN r894 (trunk)
This commit is contained in:
Christoph Oelckers 2008-04-08 20:52:49 +00:00
commit 894b663877
13 changed files with 320 additions and 325 deletions

View file

@ -71,46 +71,16 @@ static void SpawnShootDecal (AActor *t1, const FTraceResults &trace);
static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff,
fixed_t vx, fixed_t vy, fixed_t vz);
AActor *tmthing;
static int tmflags;
static fixed_t tmx;
static fixed_t tmy;
static fixed_t tmz; // [RH] Needed for third dimension of teleporters
static FRandom pr_tracebleed ("TraceBleed");
static FRandom pr_checkthing ("CheckThing");
static FRandom pr_lineattack ("LineAttack");
static FRandom pr_crunch ("DoCrunch");
// If "floatok" true, move would be ok
// if within "tmfloorz - tmceilingz".
bool floatok;
fixed_t tmfloorz;
fixed_t tmceilingz;
fixed_t tmdropoffz;
int tmfloorpic;
sector_t *tmfloorsector;
int tmceilingpic;
sector_t *tmceilingsector;
bool tmtouchmidtex;
//Added by MC: So bot will know what kind of sector it's entering.
sector_t* tmsector;
// keep track of the line that lowers the ceiling,
// so missiles don't explode against sky hack walls
line_t* ceilingline;
line_t *BlockingLine;
// keep track of special lines as they are hit,
// but don't process them until the move is proven valid
TArray<line_t *> spechit;
AActor *onmobj; // generic global onmobj...used for landing on pods/players
AActor *BlockingMobj;
// Temporary holder for thing_sectorlist threads
msecnode_t* sector_list = NULL; // phares 3/16/98
@ -219,6 +189,7 @@ void P_FindFloorCeiling (AActor *actor)
tmf.floorsector = sec;
tmf.ceilingpic = sec->ceilingpic;
tmf.ceilingsector = sec;
tmf.touchmidtex = false;
validcount++;
FBlockLinesIterator it(box);
@ -261,7 +232,6 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
// kill anything occupying the position
newsec = P_PointInSector (x,y);
ceilingline = NULL;
// The base floor/ceiling is from the subsector that contains the point.
// Any contacted lines the step closer together will adjust them.
@ -335,7 +305,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
thing->ceilingsector = tmf.ceilingsector;
thing->ceilingpic = tmf.ceilingpic;
thing->dropoffz = tmf.dropoffz; // killough 11/98
BlockingLine = NULL;
thing->BlockingLine = NULL;
if (thing->flags2 & MF2_FLOORCLIP)
{
@ -498,7 +468,7 @@ int P_GetMoveFactor (const AActor *mo, int *frictionp)
//
static // killough 3/26/98: make static
bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
{
bool rail = false;
@ -523,44 +493,44 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
if (!ld->backsector)
{ // One sided line
if (tmthing->flags2 & MF2_BLASTED)
if (tm.thing->flags2 & MF2_BLASTED)
{
P_DamageMobj (tmthing, NULL, NULL, tmthing->Mass >> 5, NAME_Melee);
P_DamageMobj (tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
}
BlockingLine = ld;
CheckForPushSpecial (ld, 0, tmthing);
tm.thing->BlockingLine = ld;
CheckForPushSpecial (ld, 0, tm.thing);
return false;
}
if (!(tmthing->flags & MF_MISSILE) || (ld->flags & ML_BLOCKEVERYTHING))
if (!(tm.thing->flags & MF_MISSILE) || (ld->flags & ML_BLOCKEVERYTHING))
{
if (ld->flags & ML_RAILING)
{
rail = true;
}
else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(tmthing->flags3 & MF3_NOBLOCKMONST) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tmthing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((ld->flags & ML_BLOCK_FLOATERS) && (tmthing->flags & MF_FLOAT))) // block floaters
(!(tm.thing->flags3 & MF3_NOBLOCKMONST) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((ld->flags & ML_BLOCK_FLOATERS) && (tm.thing->flags & MF_FLOAT))) // block floaters
{
if (tmthing->flags2 & MF2_BLASTED)
if (tm.thing->flags2 & MF2_BLASTED)
{
P_DamageMobj (tmthing, NULL, NULL, tmthing->Mass >> 5, NAME_Melee);
P_DamageMobj (tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
}
BlockingLine = ld;
CheckForPushSpecial (ld, 0, tmthing);
tm.thing->BlockingLine = ld;
CheckForPushSpecial (ld, 0, tm.thing);
return false;
}
}
// [RH] Steep sectors count as dropoffs (unless already in one)
if (!(tmthing->flags & MF_DROPOFF) &&
!(tmthing->flags & (MF_NOGRAVITY|MF_NOCLIP)))
if (!(tm.thing->flags & MF_DROPOFF) &&
!(tm.thing->flags & (MF_NOGRAVITY|MF_NOCLIP)))
{
if (ld->frontsector->floorplane.c < STEEPSLOPE ||
ld->backsector->floorplane.c < STEEPSLOPE)
{
const msecnode_t *node = tmthing->touching_sectorlist;
const msecnode_t *node = tm.thing->touching_sectorlist;
bool allow = false;
int count = 0;
while (node != NULL)
@ -589,15 +559,15 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
(ld->frontsector->ceilingplane.a | ld->frontsector->ceilingplane.b) |
(ld->backsector->ceilingplane.a | ld->backsector->ceilingplane.b)) == 0)
{
P_LineOpening (open, tmthing, ld, sx=tmx, sy=tmy, tmx, tmy);
P_LineOpening (open, tm.thing, ld, sx=tm.x, sy=tm.y, tm.x, tm.y);
}
else
{ // Find the point on the line closest to the actor's center, and use
// that to calculate openings
float dx = (float)ld->dx;
float dy = (float)ld->dy;
fixed_t r = (fixed_t)(((float)(tmx - ld->v1->x) * dx +
(float)(tmy - ld->v1->y) * dy) /
fixed_t r = (fixed_t)(((float)(tm.x - ld->v1->x) * dx +
(float)(tm.y - ld->v1->y) * dy) /
(dx*dx + dy*dy) * 16777216.f);
/* Printf ("%d:%d: %d (%d %d %d %d) (%d %d %d %d)\n", level.time, ld-lines, r,
ld->frontsector->floorplane.a,
@ -610,16 +580,16 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
ld->backsector->floorplane.ic);*/
if (r <= 0)
{
P_LineOpening (open, tmthing, ld, sx=ld->v1->x, sy=ld->v1->y, tmx, tmy);
P_LineOpening (open, tm.thing, ld, sx=ld->v1->x, sy=ld->v1->y, tm.x, tm.y);
}
else if (r >= (1<<24))
{
P_LineOpening (open, tmthing, ld, sx=ld->v2->x, sy=ld->v2->y, tmthing->x, tmthing->y);
P_LineOpening (open, tm.thing, ld, sx=ld->v2->x, sy=ld->v2->y, tm.thing->x, tm.thing->y);
}
else
{
P_LineOpening (open, tmthing, ld, sx=ld->v1->x + MulScale24 (r, ld->dx),
sy=ld->v1->y + MulScale24 (r, ld->dy), tmx, tmy);
P_LineOpening (open, tm.thing, ld, sx=ld->v1->x + MulScale24 (r, ld->dx),
sy=ld->v1->y + MulScale24 (r, ld->dy), tm.x, tm.y);
}
/* Printf (" %d %d %d\n", sx, sy, openbottom);*/
}
@ -634,32 +604,32 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
// forced to say, "It's not a bug. It's a feature?" Ugh.
(gameinfo.gametype != GAME_Strife ||
level.flags & LEVEL_HEXENFORMAT ||
open.bottom == tmthing->Sector->floorplane.ZatPoint (sx, sy)))
open.bottom == tm.thing->Sector->floorplane.ZatPoint (sx, sy)))
{
open.bottom += 32*FRACUNIT;
}
// adjust floor / ceiling heights
if (open.top < tmceilingz)
if (open.top < tm.ceilingz)
{
tmceilingz = open.top;
tmceilingsector = open.topsec;
tmceilingpic = open.ceilingpic;
ceilingline = ld;
BlockingLine = ld;
tm.ceilingz = open.top;
tm.ceilingsector = open.topsec;
tm.ceilingpic = open.ceilingpic;
tm.ceilingline = ld;
tm.thing->BlockingLine = ld;
}
if (open.bottom > tmfloorz)
if (open.bottom > tm.floorz)
{
tmfloorz = open.bottom;
tmfloorsector = open.bottomsec;
tmfloorpic = open.floorpic;
tmtouchmidtex = open.touchmidtex;
BlockingLine = ld;
tm.floorz = open.bottom;
tm.floorsector = open.bottomsec;
tm.floorpic = open.floorpic;
tm.touchmidtex = open.touchmidtex;
tm.thing->BlockingLine = ld;
}
if (open.lowfloor < tmdropoffz)
tmdropoffz = open.lowfloor;
if (open.lowfloor < tm.dropoffz)
tm.dropoffz = open.lowfloor;
// if contacted a special line, add it to the list
if (ld->special)
@ -678,34 +648,27 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
static AActor *stepthing;
bool PIT_CheckThing (AActor *thing)
bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
{
fixed_t topz;
fixed_t blockdist;
bool solid;
int damage;
// don't clip against self
if (thing == tmthing)
if (thing == tm.thing)
return true;
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
return true; // can't hit thing
blockdist = thing->radius + tmthing->radius;
if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
{
// didn't hit thing
return true;
}
BlockingMobj = thing;
tm.thing->BlockingMobj = thing;
topz = thing->z + thing->height;
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tmthing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
(thing->flags & MF_SOLID) && (thing->flags4 & MF4_ACTLIKEBRIDGE))
{
// [RH] Let monsters walk on actors as well as floors
if ((tmthing->flags3 & MF3_ISMONSTER) &&
topz >= tmfloorz && topz <= tmthing->z + tmthing->MaxStepHeight)
if ((tm.thing->flags3 & MF3_ISMONSTER) &&
topz >= tm.floorz && topz <= tm.thing->z + tm.thing->MaxStepHeight)
{
// The commented-out if is an attempt to prevent monsters from walking off a
// thing further than they would walk off a ledge. I can't think of an easy
@ -716,51 +679,51 @@ bool PIT_CheckThing (AActor *thing)
// abs(thing->y - tmy) <= thing->radius)
{
stepthing = thing;
tmfloorz = topz;
tm.floorz = topz;
}
}
}
// [RH] If the other thing is a bridge, then treat the moving thing as if it had MF2_PASSMOBJ, so
// you can use a scrolling floor to move scenery items underneath a bridge.
if ((tmthing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ))
if ((tm.thing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ))
{ // check if a mobj passed over/under another object
if (tmthing->flags3 & thing->flags3 & MF3_DONTOVERLAP)
if (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP)
{ // Some things prefer not to overlap each other, if possible
return false;
}
if ((tmthing->z >= topz) || (tmthing->z + tmthing->height <= thing->z))
if ((tm.thing->z >= topz) || (tm.thing->z + tm.thing->height <= thing->z))
{
return true;
}
}
// Check for skulls slamming into things
if (tmthing->flags & MF_SKULLFLY)
if (tm.thing->flags & MF_SKULLFLY)
{
bool res = tmthing->Slam (BlockingMobj);
BlockingMobj = NULL;
bool res = tm.thing->Slam (tm.thing->BlockingMobj);
tm.thing->BlockingMobj = NULL;
return res;
}
// Check for blasted thing running into another
if ((tmthing->flags2 & MF2_BLASTED) && (thing->flags & MF_SHOOTABLE))
if ((tm.thing->flags2 & MF2_BLASTED) && (thing->flags & MF_SHOOTABLE))
{
if (!(thing->flags2 & MF2_BOSS) && (thing->flags3 & MF3_ISMONSTER))
{
thing->momx += tmthing->momx;
thing->momy += tmthing->momy;
thing->momx += tm.thing->momx;
thing->momy += tm.thing->momy;
if ((thing->momx + thing->momy) > 3*FRACUNIT)
{
damage = (tmthing->Mass / 100) + 1;
P_DamageMobj (thing, tmthing, tmthing, damage, tmthing->DamageType);
P_TraceBleed (damage, thing, tmthing);
damage = (tm.thing->Mass / 100) + 1;
P_DamageMobj (thing, tm.thing, tm.thing, damage, tm.thing->DamageType);
P_TraceBleed (damage, thing, tm.thing);
damage = (thing->Mass / 100) + 1;
P_DamageMobj (tmthing, thing, thing, damage >> 2, tmthing->DamageType);
P_TraceBleed (damage, tmthing, thing);
P_DamageMobj (tm.thing, thing, thing, damage >> 2, tm.thing->DamageType);
P_TraceBleed (damage, tm.thing, thing);
}
return false;
}
}
// Check for missile
if (tmthing->flags & MF_MISSILE)
if (tm.thing->flags & MF_MISSILE)
{
// Check for a non-shootable mobj
if (thing->flags2 & MF2_NONSHOOTABLE)
@ -768,29 +731,29 @@ bool PIT_CheckThing (AActor *thing)
return true;
}
// Check for passing through a ghost
if ((thing->flags3 & MF3_GHOST) && (tmthing->flags2 & MF2_THRUGHOST))
if ((thing->flags3 & MF3_GHOST) && (tm.thing->flags2 & MF2_THRUGHOST))
{
return true;
}
// Check if it went over / under
if (tmthing->z > thing->z + thing->height)
if (tm.thing->z > thing->z + thing->height)
{ // Over thing
return true;
}
if (tmthing->z+tmthing->height < thing->z)
if (tm.thing->z+tm.thing->height < thing->z)
{ // Under thing
return true;
}
if (tmthing->flags2 & MF2_BOUNCE2)
if (tm.thing->flags2 & MF2_BOUNCE2)
{
if (tmthing->Damage == 0)
if (tm.thing->Damage == 0)
{
return (tmthing->target == thing || !(thing->flags & MF_SOLID));
return (tm.thing->target == thing || !(thing->flags & MF_SOLID));
}
}
switch (tmthing->SpecialMissileHit (thing))
switch (tm.thing->SpecialMissileHit (thing))
{
case 0: return false;
case 1: return true;
@ -804,16 +767,16 @@ bool PIT_CheckThing (AActor *thing)
// that ZDoom supports friendly monsters?
if (tmthing->target != NULL)
if (tm.thing->target != NULL)
{
if (thing == tmthing->target)
if (thing == tm.thing->target)
{ // Don't missile self
return true;
}
// players are never subject to infighting settings and are always allowed
// to harm / be harmed by anything.
if (!thing->player && !tmthing->target->player)
if (!thing->player && !tm.thing->target->player)
{
int infight;
if (level.flags & LEVEL_TOTALINFIGHTING) infight=1;
@ -824,7 +787,7 @@ bool PIT_CheckThing (AActor *thing)
{
// -1: Monsters cannot hurt each other, but make exceptions for
// friendliness and hate status.
if (tmthing->target->flags & MF_SHOOTABLE)
if (tm.thing->target->flags & MF_SHOOTABLE)
{
if (!(thing->flags3 & MF3_ISMONSTER))
{
@ -833,10 +796,10 @@ bool PIT_CheckThing (AActor *thing)
}
// Monsters that are clearly hostile can always hurt each other
if (!thing->IsHostile (tmthing->target))
if (!thing->IsHostile (tm.thing->target))
{
// The same if the shooter hates the target
if (thing->tid == 0 || tmthing->target->TIDtoHate != thing->tid)
if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid)
{
return false;
}
@ -847,24 +810,24 @@ bool PIT_CheckThing (AActor *thing)
{
// 0: Monsters cannot hurt same species except
// cases where they are clearly supposed to do that
if (thing->IsFriend (tmthing->target))
if (thing->IsFriend (tm.thing->target))
{
// Friends never harm each other
return false;
}
if (thing->TIDtoHate != 0 && thing->TIDtoHate == tmthing->target->TIDtoHate)
if (thing->TIDtoHate != 0 && thing->TIDtoHate == tm.thing->target->TIDtoHate)
{
// [RH] Don't hurt monsters that hate the same thing as you do
return false;
}
if (thing->GetSpecies() == tmthing->target->GetSpecies())
if (thing->GetSpecies() == tm.thing->target->GetSpecies())
{
// Don't hurt same species or any relative -
// but only if the target isn't one's hostile.
if (!thing->IsHostile (tmthing->target))
if (!thing->IsHostile (tm.thing->target))
{
// Allow hurting monsters the shooter hates.
if (thing->tid == 0 || tmthing->target->TIDtoHate != thing->tid)
if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid)
{
return false;
}
@ -878,7 +841,7 @@ bool PIT_CheckThing (AActor *thing)
{ // Didn't do any damage
return !(thing->flags & MF_SOLID);
}
if ((thing->flags4 & MF4_SPECTRAL) && !(tmthing->flags4 & MF4_SPECTRAL))
if ((thing->flags4 & MF4_SPECTRAL) && !(tm.thing->flags4 & MF4_SPECTRAL))
{
return true;
}
@ -889,45 +852,45 @@ bool PIT_CheckThing (AActor *thing)
LastRipped = thing;
if (!(thing->flags & MF_NOBLOOD) &&
!(thing->flags2 & MF2_REFLECTIVE) &&
!(tmthing->flags3 & MF3_BLOODLESSIMPACT) &&
!(tm.thing->flags3 & MF3_BLOODLESSIMPACT) &&
!(thing->flags2 & (MF2_INVULNERABLE|MF2_DORMANT)))
{ // Ok to spawn blood
P_RipperBlood (tmthing, thing);
P_RipperBlood (tm.thing, thing);
}
S_Sound (tmthing, CHAN_BODY, "misc/ripslop", 1, ATTN_IDLE);
damage = tmthing->GetMissileDamage (3, 2);
P_DamageMobj (thing, tmthing, tmthing->target, damage, tmthing->DamageType);
if (!(tmthing->flags3 & MF3_BLOODLESSIMPACT))
S_Sound (tm.thing, CHAN_BODY, "misc/ripslop", 1, ATTN_IDLE);
damage = tm.thing->GetMissileDamage (3, 2);
P_DamageMobj (thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType);
if (!(tm.thing->flags3 & MF3_BLOODLESSIMPACT))
{
P_TraceBleed (damage, thing, tmthing);
P_TraceBleed (damage, thing, tm.thing);
}
if (thing->flags2 & MF2_PUSHABLE
&& !(tmthing->flags2 & MF2_CANNOTPUSH))
&& !(tm.thing->flags2 & MF2_CANNOTPUSH))
{ // Push thing
thing->momx += tmthing->momx>>2;
thing->momy += tmthing->momy>>2;
thing->momx += tm.thing->momx>>2;
thing->momy += tm.thing->momy>>2;
}
}
spechit.Clear ();
return true;
}
// Do damage
damage = tmthing->GetMissileDamage ((tmthing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1);
damage = tm.thing->GetMissileDamage ((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1);
if (damage > 0)
{
P_DamageMobj (thing, tmthing, tmthing->target, damage, tmthing->DamageType);
if ((tmthing->flags5 & MF5_BLOODSPLATTER) &&
P_DamageMobj (thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType);
if ((tm.thing->flags5 & MF5_BLOODSPLATTER) &&
!(thing->flags & MF_NOBLOOD) &&
!(thing->flags2 & MF2_REFLECTIVE) &&
!(thing->flags2 & (MF2_INVULNERABLE|MF2_DORMANT)) &&
!(tmthing->flags3 & MF3_BLOODLESSIMPACT) &&
!(tm.thing->flags3 & MF3_BLOODLESSIMPACT) &&
(pr_checkthing() < 192))
{
P_BloodSplatter (tmthing->x, tmthing->y, tmthing->z, thing);
P_BloodSplatter (tm.thing->x, tm.thing->y, tm.thing->z, thing);
}
if (!(tmthing->flags3 & MF3_BLOODLESSIMPACT))
if (!(tm.thing->flags3 & MF3_BLOODLESSIMPACT))
{
P_TraceBleed (damage, thing, tmthing);
P_TraceBleed (damage, thing, tm.thing);
}
}
else if (damage < 0)
@ -936,23 +899,23 @@ bool PIT_CheckThing (AActor *thing)
}
return false; // don't traverse any more
}
if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH) &&
(tmthing->player == NULL || !(tmthing->player->cheats & CF_PREDICTING)))
if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH) &&
(tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)))
{ // Push thing
thing->momx += tmthing->momx >> 2;
thing->momy += tmthing->momy >> 2;
thing->momx += tm.thing->momx >> 2;
thing->momy += tm.thing->momy >> 2;
}
solid = (thing->flags & MF_SOLID) &&
!(thing->flags & MF_NOCLIP) &&
(tmthing->flags & MF_SOLID);
(tm.thing->flags & MF_SOLID);
// Check for special pickup
if ((thing->flags & MF_SPECIAL) && (tmflags & MF_PICKUP)
if ((thing->flags & MF_SPECIAL) && (tm.thing->flags & MF_PICKUP)
// [RH] The next condition is to compensate for the extra height
// that gets added by P_CheckPosition() so that you cannot pick
// up things that are above your true height.
&& thing->z < tmthing->z + tmthing->height - tmthing->MaxStepHeight)
&& thing->z < tm.thing->z + tm.thing->height - tm.thing->MaxStepHeight)
{ // Can be picked up by tmthing
P_TouchSpecialThing (thing, tmthing); // can remove thing
P_TouchSpecialThing (thing, tm.thing); // can remove thing
}
// killough 3/16/98: Allow non-solid moving objects to move through solid
@ -1008,6 +971,7 @@ bool P_TestMobjLocation (AActor *mobj)
return false;
}
//
// P_CheckPosition
// This is purely informative, nothing is modified
@ -1031,44 +995,41 @@ bool P_TestMobjLocation (AActor *mobj)
// numspeciallines
// AActor *BlockingMobj = pointer to thing that blocked position (NULL if not
// blocked, or blocked by a line).
bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
{
static TArray<AActor *> checkpbt;
sector_t *newsec;
AActor *thingblocker;
AActor *fakedblocker;
fixed_t realheight = thing->height;
tmthing = thing;
tmflags = thing->flags;
tm.thing = thing;
tmx = x;
tmy = y;
tm.x = x;
tm.y = y;
FBoundingBox box(x, y, thing->radius);
newsec = P_PointInSector (x,y);
ceilingline = BlockingLine = NULL;
tm.ceilingline = thing->BlockingLine = NULL;
// The base floor / ceiling is from the subsector that contains the point.
// Any contacted lines the step closer together will adjust them.
tmfloorz = tmdropoffz = newsec->floorplane.ZatPoint (x, y);
tmceilingz = newsec->ceilingplane.ZatPoint (x, y);
tmfloorpic = newsec->floorpic;
tmfloorsector = newsec;
tmceilingpic = newsec->ceilingpic;
tmceilingsector = newsec;
tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint (x, y);
tm.ceilingz = newsec->ceilingplane.ZatPoint (x, y);
tm.floorpic = newsec->floorpic;
tm.floorsector = newsec;
tm.ceilingpic = newsec->ceilingpic;
tm.ceilingsector = newsec;
tm.touchmidtex = false;
//Added by MC: Fill the tmsector.
tmsector = newsec;
tm.sector = newsec;
validcount++;
spechit.Clear ();
checkpbt.Clear ();
if ((tmflags & MF_NOCLIP) && !(tmflags & MF_SKULLFLY))
if ((thing->flags & MF_NOCLIP) && !(thing->flags & MF_SKULLFLY))
return true;
// Check things first, possibly picking things up.
@ -1076,7 +1037,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
// because DActors are grouped into mapblocks
// based on their origin point, and can overlap
// into adjacent blocks by up to MAXRADIUS units.
BlockingMobj = NULL;
thing->BlockingMobj = NULL;
thingblocker = NULL;
fakedblocker = NULL;
if (thing->player)
@ -1090,11 +1051,13 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
AActor *th;
while ((th = it2.Next()))
{
if (!PIT_CheckThing(th))
if (!PIT_CheckThing(th, tm))
{ // [RH] If a thing can be stepped up on, we need to continue checking
// other things in the blocks and see if we hit something that is
// definitely blocking. Otherwise, we need to check the lines, or we
// could end up stuck inside a wall.
AActor *BlockingMobj = thing->BlockingMobj;
if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ))
{ // Thing slammed into something; don't let it move now.
thing->height = realheight;
@ -1108,7 +1071,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
{
thingblocker = BlockingMobj;
}
BlockingMobj = NULL;
thing->BlockingMobj = NULL;
}
else if (thing->player &&
thing->z + thing->height - BlockingMobj->z <= thing->MaxStepHeight)
@ -1122,7 +1085,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
// Nothing is blocking us, but this actor potentially could
// if there is something else to step on.
fakedblocker = BlockingMobj;
BlockingMobj = NULL;
thing->BlockingMobj = NULL;
}
else
{ // Definitely blocking
@ -1145,32 +1108,38 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
// being considered for collision with the player.
validcount++;
BlockingMobj = NULL;
thing->BlockingMobj = NULL;
thing->height = realheight;
if (tmflags & MF_NOCLIP)
return (BlockingMobj = thingblocker) == NULL;
if (thing->flags & MF_NOCLIP)
return (thing->BlockingMobj = thingblocker) == NULL;
FBlockLinesIterator it(box);
line_t *ld;
fixed_t thingdropoffz = tmfloorz;
fixed_t thingdropoffz = tm.floorz;
//bool onthing = (thingdropoffz != tmdropoffz);
tmfloorz = tmdropoffz;
tm.floorz = tm.dropoffz;
while ((ld = it.Next()))
{
if (!PIT_CheckLine(ld, box)) return false;
if (!PIT_CheckLine(ld, box, tm)) return false;
}
if (tmceilingz - tmfloorz < thing->height)
if (tm.ceilingz - tm.floorz < thing->height)
return false;
if (stepthing != NULL || tmtouchmidtex)
if (stepthing != NULL || tm.touchmidtex)
{
tmdropoffz = thingdropoffz;
tm.dropoffz = thingdropoffz;
}
return (BlockingMobj = thingblocker) == NULL;
return (thing->BlockingMobj = thingblocker) == NULL;
}
bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
{
FCheckPosition tm;
return P_CheckPosition(thing, x, y, tm);
}
//=============================================================================
@ -1327,7 +1296,8 @@ static void CheckForPushSpecial (line_t *line, int side, AActor *mobj)
//
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
bool dropoff, // killough 3/15/98: allow dropoff as option
bool onfloor) // [RH] Let P_TryMove keep the thing on the floor
bool onfloor, // [RH] Let P_TryMove keep the thing on the floor
FCheckPosition &tm)
{
fixed_t oldx;
fixed_t oldy;
@ -1338,14 +1308,15 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
sector_t* oldsec = thing->Sector; // [RH] for sector actions
sector_t* newsec;
floatok = false;
tm.floatok = false;
oldz = thing->z;
if (onfloor)
{
thing->z = thing->floorsector->floorplane.ZatPoint (x, y);
}
if (!P_CheckPosition (thing, x, y))
if (!P_CheckPosition (thing, x, y, tm))
{
AActor *BlockingMobj = thing->BlockingMobj;
// Solid wall or thing
if (!BlockingMobj || BlockingMobj->player || !thing->player)
{
@ -1361,13 +1332,13 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
> thing->MaxStepHeight
|| (BlockingMobj->Sector->ceilingplane.ZatPoint (x, y)
- (BlockingMobj->z+BlockingMobj->height) < thing->height)
|| (tmceilingz-(BlockingMobj->z+BlockingMobj->height)
|| (tm.ceilingz-(BlockingMobj->z+BlockingMobj->height)
< thing->height))
{
goto pushline;
}
}
if (!(tmthing->flags2 & MF2_PASSMOBJ) || (i_compatflags & COMPATF_NO_PASSMOBJ))
if (!(tm.thing->flags2 & MF2_PASSMOBJ) || (i_compatflags & COMPATF_NO_PASSMOBJ))
{
thing->z = oldz;
return false;
@ -1376,28 +1347,28 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
if (thing->flags3 & MF3_FLOORHUGGER)
{
thing->z = tmfloorz;
thing->z = tm.floorz;
}
else if (thing->flags3 & MF3_CEILINGHUGGER)
{
thing->z = tmceilingz - thing->height;
thing->z = tm.ceilingz - thing->height;
}
if (onfloor && tmfloorsector == thing->floorsector)
if (onfloor && tm.floorsector == thing->floorsector)
{
thing->z = tmfloorz;
thing->z = tm.floorz;
}
if (!(thing->flags & MF_NOCLIP))
{
if (tmceilingz - tmfloorz < thing->height)
if (tm.ceilingz - tm.floorz < thing->height)
{
goto pushline; // doesn't fit
}
floatok = true;
tm.floatok = true;
if (!(thing->flags & MF_TELEPORT)
&& tmceilingz - thing->z < thing->height
&& tm.ceilingz - thing->z < thing->height
&& !(thing->flags3 & MF3_CEILINGHUGGER)
&& (!(thing->flags2 & MF2_FLY) || !(thing->flags & MF_NOGRAVITY)))
{
@ -1406,7 +1377,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
if (thing->flags2 & MF2_FLY && thing->flags & MF_NOGRAVITY)
{
#if 1
if (thing->z+thing->height > tmceilingz)
if (thing->z+thing->height > tm.ceilingz)
goto pushline;
#else
// When flying, slide up or down blocking lines until the actor
@ -1425,19 +1396,19 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
}
if (!(thing->flags & MF_TELEPORT) && !(thing->flags3 & MF3_FLOORHUGGER))
{
if (tmfloorz-thing->z > thing->MaxStepHeight)
if (tm.floorz-thing->z > thing->MaxStepHeight)
{ // too big a step up
goto pushline;
}
else if ((thing->flags & MF_MISSILE) && tmfloorz > thing->z)
else if ((thing->flags & MF_MISSILE) && tm.floorz > thing->z)
{ // [RH] Don't let normal missiles climb steps
goto pushline;
}
else if (thing->z < tmfloorz)
else if (thing->z < tm.floorz)
{ // [RH] Check to make sure there's nothing in the way for the step up
fixed_t savedz = thing->z;
bool good;
thing->z = tmfloorz;
thing->z = tm.floorz;
good = P_TestMobjZ (thing);
thing->z = savedz;
if (!good)
@ -1452,15 +1423,15 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
{
if (!(thing->flags5&MF5_AVOIDINGDROPOFF))
{
fixed_t floorz = tmfloorz;
fixed_t floorz = tm.floorz;
// [RH] If the thing is standing on something, use its current z as the floorz.
// This is so that it does not walk off of things onto a drop off.
if (thing->flags2 & MF2_ONMOBJ)
{
floorz = MAX(thing->z, tmfloorz);
floorz = MAX(thing->z, tm.floorz);
}
if (floorz - tmdropoffz > thing->MaxDropOffHeight &&
if (floorz - tm.dropoffz > thing->MaxDropOffHeight &&
!(thing->flags2 & MF2_BLASTED))
{ // Can't move over a dropoff unless it's been blasted
thing->z = oldz;
@ -1471,13 +1442,13 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
{
// special logic to move a monster off a dropoff
// this intentionally does not check for standing on things.
if (thing->floorz - tmfloorz > thing->MaxDropOffHeight ||
thing->dropoffz - tmdropoffz > thing->MaxDropOffHeight) return false;
if (thing->floorz - tm.floorz > thing->MaxDropOffHeight ||
thing->dropoffz - tm.dropoffz > thing->MaxDropOffHeight) return false;
}
}
if (thing->flags2 & MF2_CANTLEAVEFLOORPIC
&& (tmfloorpic != thing->floorpic
|| tmfloorz - thing->z != 0))
&& (tm.floorpic != thing->floorpic
|| tm.floorz - thing->z != 0))
{ // must stay within a sector of a certain floor type
thing->z = oldz;
return false;
@ -1486,8 +1457,8 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
//Added by MC: To prevent bot from getting into dangerous sectors.
if (thing->player && thing->player->isbot && thing->flags & MF_SHOOTABLE)
{
if (tmsector != thing->Sector
&& bglobal.IsDangerous (tmsector))
if (tm.sector != thing->Sector
&& bglobal.IsDangerous (tm.sector))
{
thing->player->prev = thing->player->dest;
thing->player->dest = NULL;
@ -1521,13 +1492,13 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
oldx = thing->x;
oldy = thing->y;
thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz;
thing->dropoffz = tmdropoffz; // killough 11/98: keep track of dropoffs
thing->floorpic = tmfloorpic;
thing->floorsector = tmfloorsector;
thing->ceilingpic = tmceilingpic;
thing->ceilingsector = tmceilingsector;
thing->floorz = tm.floorz;
thing->ceilingz = tm.ceilingz;
thing->dropoffz = tm.dropoffz; // killough 11/98: keep track of dropoffs
thing->floorpic = tm.floorpic;
thing->floorsector = tm.floorsector;
thing->ceilingpic = tm.ceilingpic;
thing->ceilingsector = tm.ceilingsector;
thing->x = x;
thing->y = y;
@ -1653,9 +1624,9 @@ pushline:
{
int numSpecHitTemp;
if (tmthing->flags2 & MF2_BLASTED)
if (tm.thing->flags2 & MF2_BLASTED)
{
P_DamageMobj (tmthing, NULL, NULL, tmthing->Mass >> 5, NAME_Melee);
P_DamageMobj (tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
}
numSpecHitTemp = (int)spechit.Size ();
while (numSpecHitTemp > 0)
@ -1669,6 +1640,16 @@ pushline:
return false;
}
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
bool dropoff, // killough 3/15/98: allow dropoff as option
bool onfloor) // [RH] Let P_TryMove keep the thing on the floor
{
FCheckPosition tm;
return P_TryMove(thing, x, y, dropoff, onfloor, tm);
}
//
// SLIDE MOVE
// Allows the player to slide along any angled walls.
@ -2216,9 +2197,9 @@ bool P_BounceWall (AActor *mo)
leady = mo->y-mo->radius;
}
bestslidefrac = FRACUNIT+1;
bestslideline = BlockingLine;
bestslideline = mo->BlockingLine;
if (P_PathTraverse(leadx, leady, leadx+mo->momx, leady+mo->momy,
PT_ADDLINES, PTR_BounceTraverse) && BlockingLine == NULL)
PT_ADDLINES, PTR_BounceTraverse) && mo->BlockingLine == NULL)
{ // Could not find a wall, so bounce off the floor/ceiling instead.
fixed_t floordist = mo->z - mo->floorz;
fixed_t ceildist = mo->ceilingz - mo->z;
@ -3588,6 +3569,7 @@ EXTERN_CVAR (Int, cl_bloodtype)
bool P_AdjustFloorCeil (AActor *thing, FChangePosition *cpos)
{
int flags2 = thing->flags2 & MF2_PASSMOBJ;
FCheckPosition tm;
if (cpos->movemidtex)
{
@ -3597,14 +3579,14 @@ bool P_AdjustFloorCeil (AActor *thing, FChangePosition *cpos)
thing->flags2 |= MF2_PASSMOBJ;
}
bool isgood = P_CheckPosition (thing, thing->x, thing->y);
thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz;
thing->dropoffz = tmdropoffz; // killough 11/98: remember dropoffs
thing->floorpic = tmfloorpic;
thing->floorsector = tmfloorsector;
thing->ceilingpic = tmceilingpic;
thing->ceilingsector = tmceilingsector;
bool isgood = P_CheckPosition (thing, thing->x, thing->y, tm);
thing->floorz = tm.floorz;
thing->ceilingz = tm.ceilingz;
thing->dropoffz = tm.dropoffz; // killough 11/98: remember dropoffs
thing->floorpic = tm.floorpic;
thing->floorsector = tm.floorsector;
thing->ceilingpic = tm.ceilingpic;
thing->ceilingsector = tm.ceilingsector;
// restore the PASSMOBJ flag but leave the other flags alone.
thing->flags2 = (thing->flags2 & ~MF2_PASSMOBJ) | flags2;
@ -3676,7 +3658,7 @@ void P_FindBelowIntersectors (AActor *actor)
{ // [RH] Corpses and specials don't block moves
continue;
}
if (thing == tmthing)
if (thing == actor)
{ // Don't clip against self
continue;
}