mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- refactoring of PIT_CheckThing.
This commit is contained in:
parent
98c7fabb89
commit
ca2fc47fa3
2 changed files with 57 additions and 51 deletions
|
@ -290,6 +290,7 @@ enum
|
|||
FFCF_NOPORTALS = 16, // ignore portals (considers them impassable.)
|
||||
FFCF_NOFLOOR = 32,
|
||||
FFCF_NOCEILING = 64,
|
||||
FFCF_RESTRICTEDPORTAL = 128, // current values in the iterator's return are through a restricted portal type (i.e. some features are blocked.)
|
||||
};
|
||||
void P_FindFloorCeiling (AActor *actor, int flags=0);
|
||||
|
||||
|
|
107
src/p_map.cpp
107
src/p_map.cpp
|
@ -76,6 +76,7 @@ static FRandom pr_crunch("DoCrunch");
|
|||
// keep track of special lines as they are hit,
|
||||
// but don't process them until the move is proven valid
|
||||
TArray<line_t *> spechit;
|
||||
TArray<line_t *> portalhit;
|
||||
|
||||
// Temporary holder for thing_sectorlist threads
|
||||
msecnode_t* sector_list = NULL; // phares 3/16/98
|
||||
|
@ -415,8 +416,6 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
|
|||
tmf.abovemidtex = false;
|
||||
P_GetFloorCeilingZ(tmf, 0);
|
||||
|
||||
spechit.Clear();
|
||||
|
||||
bool StompAlwaysFrags = ((thing->flags2 & MF2_TELESTOMP) || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag) && !(thing->flags7 & MF7_NOTELESTOMP);
|
||||
|
||||
// P_LineOpening requires the thing's z to be the destination z in order to work.
|
||||
|
@ -839,7 +838,6 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
|||
if (!(tm.thing->flags & MF_DROPOFF) &&
|
||||
!(tm.thing->flags & (MF_NOGRAVITY | MF_NOCLIP)))
|
||||
{
|
||||
// Check 3D floors as well
|
||||
if ((open.frontfloorplane.c < STEEPSLOPE) != (open.backfloorplane.c < STEEPSLOPE))
|
||||
{
|
||||
// on the boundary of a steep slope
|
||||
|
@ -847,7 +845,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
|||
}
|
||||
}
|
||||
|
||||
// If the floor planes on both sides we should recalculate open.bottom at the actual position we are checking
|
||||
// If the floor planes on both sides match we should recalculate open.bottom at the actual position we are checking
|
||||
// This is to avoid bumpy movement when crossing a linedef with the same slope on both sides.
|
||||
if (open.frontfloorplane == open.backfloorplane)
|
||||
{
|
||||
|
@ -902,6 +900,10 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
|||
{
|
||||
spechit.Push(ld);
|
||||
}
|
||||
if (ld->portalindex >= 0)
|
||||
{
|
||||
portalhit.Push(ld);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1013,9 +1015,8 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
if (!((thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY))
|
||||
return true; // can't hit thing
|
||||
|
||||
fixedvec3 thingpos = thing->PosRelative(tm.thing);
|
||||
fixed_t blockdist = thing->radius + tm.thing->radius;
|
||||
if (abs(thingpos.x - tm.x) >= blockdist || abs(thingpos.y - tm.y) >= blockdist)
|
||||
if (abs(thing->X() - cres.position.x) >= blockdist || abs(thing->Y() - cres.position.y) >= blockdist)
|
||||
return true;
|
||||
|
||||
if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS)
|
||||
|
@ -1026,50 +1027,55 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
|
||||
tm.thing->BlockingMobj = thing;
|
||||
topz = thing->Top();
|
||||
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 ((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
|
||||
// way to do this, so I restrict them to only walking on bridges instead.
|
||||
// Uncommenting the if here makes it almost impossible for them to walk on
|
||||
// anything, bridge or otherwise.
|
||||
// if (abs(thing->x - tmx) <= thing->radius &&
|
||||
// abs(thing->y - tmy) <= thing->radius)
|
||||
{
|
||||
tm.stepthing = thing;
|
||||
tm.floorz = topz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Both things overlap in x or y direction
|
||||
bool unblocking = false;
|
||||
|
||||
if ((tm.FromPMove || tm.thing->player != NULL) && thing->flags&MF_SOLID)
|
||||
// walking on other actors and unblocking is too messy through restricted portal types so disable it.
|
||||
if (!(cres.portalflags & FFCF_RESTRICTEDPORTAL))
|
||||
{
|
||||
// Both actors already overlap. To prevent them from remaining stuck allow the move if it
|
||||
// takes them further apart or the move does not change the position (when called from P_ChangeSector.)
|
||||
if (tm.x == tm.thing->X() && tm.y == tm.thing->Y())
|
||||
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))
|
||||
{
|
||||
unblocking = true;
|
||||
}
|
||||
else if (abs(thingpos.x - tm.thing->X()) < (thing->radius+tm.thing->radius) &&
|
||||
abs(thingpos.y - tm.thing->Y()) < (thing->radius+tm.thing->radius))
|
||||
|
||||
{
|
||||
fixed_t newdist = thing->AproxDistance(tm.x, tm.y, tm.thing);
|
||||
fixed_t olddist = thing->AproxDistance(tm.thing);
|
||||
|
||||
if (newdist > olddist)
|
||||
// [RH] Let monsters walk on actors as well as floors
|
||||
if (cres.zdiff != 0 && (tm.thing->flags3 & MF3_ISMONSTER) &&
|
||||
topz >= tm.floorz && topz <= cres.position.z + tm.thing->MaxStepHeight)
|
||||
{
|
||||
// ... but not if they did not overlap in z-direction before but would after the move.
|
||||
unblocking = !((tm.thing->Z() >= topz && tm.z < topz) ||
|
||||
(tm.thing->Top() <= thingpos.z && tm.thing->Top() > thingpos.z));
|
||||
// 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
|
||||
// way to do this, so I restrict them to only walking on bridges instead.
|
||||
// Uncommenting the if here makes it almost impossible for them to walk on
|
||||
// anything, bridge or otherwise.
|
||||
// if (abs(thing->x - tmx) <= thing->radius &&
|
||||
// abs(thing->y - tmy) <= thing->radius)
|
||||
{
|
||||
tm.stepthing = thing;
|
||||
tm.floorz = topz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((tm.FromPMove || tm.thing->player != NULL) && thing->flags&MF_SOLID))
|
||||
{
|
||||
fixedvec3 oldpos = tm.thing->PosRelative(thing);
|
||||
// Both actors already overlap. To prevent them from remaining stuck allow the move if it
|
||||
// takes them further apart or the move does not change the position (when called from P_ChangeSector.)
|
||||
if (oldpos.x == thing->X() && oldpos.y == thing->Y())
|
||||
{
|
||||
unblocking = true;
|
||||
}
|
||||
else if (abs(thing->X() - oldpos.x) < (thing->radius + tm.thing->radius) &&
|
||||
abs(thing->Y() - oldpos.y) < (thing->radius + tm.thing->radius))
|
||||
|
||||
{
|
||||
fixed_t newdist = thing->AproxDistance(cres.position.x, cres.position.y);
|
||||
fixed_t olddist = thing->AproxDistance(oldpos.x, oldpos.y);
|
||||
|
||||
if (newdist > olddist)
|
||||
{
|
||||
// unblock only if there's already a vertical overlap (or both actors are flagged not to overlap)
|
||||
unblocking = (cres.position.z + tm.thing->height > thing->Z() && cres.position.z < topz) || (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1087,7 +1093,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
{ // Some things prefer not to overlap each other, if possible
|
||||
return unblocking;
|
||||
}
|
||||
if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z()))
|
||||
if ((cres.position.z >= topz) || (cres.position.z + tm.thing->height <= thing->Z()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1103,7 +1109,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
// or different species if DONTHARMSPECIES
|
||||
(!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) &&
|
||||
// touches vertically
|
||||
topz >= tm.thing->Z() && tm.thing->Z() + tm.thing->height >= thingpos.z &&
|
||||
topz >= cres.position.z && cres.position.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
|
||||
|
@ -1206,11 +1212,11 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
}
|
||||
|
||||
// Check if it went over / under
|
||||
if (tm.thing->Z() > thingpos.z + clipheight)
|
||||
if (cres.position.z > thing->Z() + clipheight)
|
||||
{ // Over thing
|
||||
return true;
|
||||
}
|
||||
if (tm.thing->Top() < thingpos.z)
|
||||
if (cres.position.z + tm.thing->height < thing->Z())
|
||||
{ // Under thing
|
||||
return true;
|
||||
}
|
||||
|
@ -1361,7 +1367,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
// [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.
|
||||
&& thingpos.z < tm.thing->Top() - tm.thing->MaxStepHeight)
|
||||
&& thing->Z() < cres.position.z + tm.thing->height - tm.thing->MaxStepHeight)
|
||||
{ // Can be picked up by tmthing
|
||||
P_TouchSpecialThing(thing, tm.thing); // can remove thing
|
||||
}
|
||||
|
@ -1476,8 +1482,8 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
|
|||
// could end up stuck inside a wall.
|
||||
AActor *BlockingMobj = thing->BlockingMobj;
|
||||
|
||||
// If this blocks through a line portal with a vertical displacement, it will always completely block. There is no way to step up onto such an actor.
|
||||
if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ) || tcres.zdiff != 0)
|
||||
// If this blocks through a restricted line portal, it will always completely block.
|
||||
if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL))
|
||||
{ // Thing slammed into something; don't let it move now.
|
||||
thing->height = realheight;
|
||||
return false;
|
||||
|
@ -1533,7 +1539,6 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
|
|||
|
||||
FMultiBlockLinesIterator it(pcheck, thing);
|
||||
FMultiBlockLinesIterator::CheckResult lcres;
|
||||
line_t *ld;
|
||||
|
||||
fixed_t thingdropoffz = tm.floorz;
|
||||
//bool onthing = (thingdropoffz != tmdropoffz);
|
||||
|
|
Loading…
Reference in a new issue