- refactoring of PIT_CheckThing.

This commit is contained in:
Christoph Oelckers 2016-02-21 19:06:56 +01:00
parent 98c7fabb89
commit ca2fc47fa3
2 changed files with 57 additions and 51 deletions

View file

@ -290,6 +290,7 @@ enum
FFCF_NOPORTALS = 16, // ignore portals (considers them impassable.) FFCF_NOPORTALS = 16, // ignore portals (considers them impassable.)
FFCF_NOFLOOR = 32, FFCF_NOFLOOR = 32,
FFCF_NOCEILING = 64, 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); void P_FindFloorCeiling (AActor *actor, int flags=0);

View file

@ -76,6 +76,7 @@ static FRandom pr_crunch("DoCrunch");
// keep track of special lines as they are hit, // keep track of special lines as they are hit,
// but don't process them until the move is proven valid // but don't process them until the move is proven valid
TArray<line_t *> spechit; TArray<line_t *> spechit;
TArray<line_t *> portalhit;
// Temporary holder for thing_sectorlist threads // Temporary holder for thing_sectorlist threads
msecnode_t* sector_list = NULL; // phares 3/16/98 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; tmf.abovemidtex = false;
P_GetFloorCeilingZ(tmf, 0); P_GetFloorCeilingZ(tmf, 0);
spechit.Clear();
bool StompAlwaysFrags = ((thing->flags2 & MF2_TELESTOMP) || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag) && !(thing->flags7 & MF7_NOTELESTOMP); 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. // 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) && if (!(tm.thing->flags & MF_DROPOFF) &&
!(tm.thing->flags & (MF_NOGRAVITY | MF_NOCLIP))) !(tm.thing->flags & (MF_NOGRAVITY | MF_NOCLIP)))
{ {
// Check 3D floors as well
if ((open.frontfloorplane.c < STEEPSLOPE) != (open.backfloorplane.c < STEEPSLOPE)) if ((open.frontfloorplane.c < STEEPSLOPE) != (open.backfloorplane.c < STEEPSLOPE))
{ {
// on the boundary of a steep slope // 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. // This is to avoid bumpy movement when crossing a linedef with the same slope on both sides.
if (open.frontfloorplane == open.backfloorplane) if (open.frontfloorplane == open.backfloorplane)
{ {
@ -902,6 +900,10 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
{ {
spechit.Push(ld); spechit.Push(ld);
} }
if (ld->portalindex >= 0)
{
portalhit.Push(ld);
}
return true; 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)) if (!((thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY))
return true; // can't hit thing return true; // can't hit thing
fixedvec3 thingpos = thing->PosRelative(tm.thing);
fixed_t blockdist = thing->radius + tm.thing->radius; 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; return true;
if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS) if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS)
@ -1026,12 +1027,19 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
tm.thing->BlockingMobj = thing; tm.thing->BlockingMobj = thing;
topz = thing->Top(); topz = thing->Top();
// Both things overlap in x or y direction
bool unblocking = false;
// walking on other actors and unblocking is too messy through restricted portal types so disable it.
if (!(cres.portalflags & FFCF_RESTRICTEDPORTAL))
{
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->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)) (thing->flags & MF_SOLID) && (thing->flags4 & MF4_ACTLIKEBRIDGE))
{ {
// [RH] Let monsters walk on actors as well as floors // [RH] Let monsters walk on actors as well as floors
if ((tm.thing->flags3 & MF3_ISMONSTER) && if (cres.zdiff != 0 && (tm.thing->flags3 & MF3_ISMONSTER) &&
topz >= tm.floorz && topz <= tm.thing->Z() + tm.thing->MaxStepHeight) topz >= tm.floorz && topz <= cres.position.z + tm.thing->MaxStepHeight)
{ {
// The commented-out if is an attempt to prevent monsters from walking off a // 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 // thing further than they would walk off a ledge. I can't think of an easy
@ -1047,29 +1055,27 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
} }
} }
// Both things overlap in x or y direction if (((tm.FromPMove || tm.thing->player != NULL) && thing->flags&MF_SOLID))
bool unblocking = false;
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 // 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.) // 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 (oldpos.x == thing->X() && oldpos.y == thing->Y())
{ {
unblocking = true; unblocking = true;
} }
else if (abs(thingpos.x - tm.thing->X()) < (thing->radius+tm.thing->radius) && else if (abs(thing->X() - oldpos.x) < (thing->radius + tm.thing->radius) &&
abs(thingpos.y - tm.thing->Y()) < (thing->radius+tm.thing->radius)) abs(thing->Y() - oldpos.y) < (thing->radius + tm.thing->radius))
{ {
fixed_t newdist = thing->AproxDistance(tm.x, tm.y, tm.thing); fixed_t newdist = thing->AproxDistance(cres.position.x, cres.position.y);
fixed_t olddist = thing->AproxDistance(tm.thing); fixed_t olddist = thing->AproxDistance(oldpos.x, oldpos.y);
if (newdist > olddist) if (newdist > olddist)
{ {
// ... but not if they did not overlap in z-direction before but would after the move. // unblock only if there's already a vertical overlap (or both actors are flagged not to overlap)
unblocking = !((tm.thing->Z() >= topz && tm.z < topz) || unblocking = (cres.position.z + tm.thing->height > thing->Z() && cres.position.z < topz) || (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP);
(tm.thing->Top() <= thingpos.z && tm.thing->Top() > thingpos.z)); }
} }
} }
} }
@ -1087,7 +1093,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
{ // Some things prefer not to overlap each other, if possible { // Some things prefer not to overlap each other, if possible
return unblocking; 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; return true;
} }
} }
@ -1103,7 +1109,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
// or different species if DONTHARMSPECIES // or different species if DONTHARMSPECIES
(!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) && (!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) &&
// touches vertically // 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 // prevents lost souls from exploding when fired by pain elementals
(thing->master != tm.thing && tm.thing->master != thing)) (thing->master != tm.thing && tm.thing->master != thing))
// Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species // 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 // Check if it went over / under
if (tm.thing->Z() > thingpos.z + clipheight) if (cres.position.z > thing->Z() + clipheight)
{ // Over thing { // Over thing
return true; return true;
} }
if (tm.thing->Top() < thingpos.z) if (cres.position.z + tm.thing->height < thing->Z())
{ // Under thing { // Under thing
return true; return true;
} }
@ -1361,7 +1367,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
// [RH] The next condition is to compensate for the extra height // [RH] The next condition is to compensate for the extra height
// that gets added by P_CheckPosition() so that you cannot pick // that gets added by P_CheckPosition() so that you cannot pick
// up things that are above your true height. // 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 { // Can be picked up by tmthing
P_TouchSpecialThing(thing, tm.thing); // can remove thing 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. // could end up stuck inside a wall.
AActor *BlockingMobj = thing->BlockingMobj; 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 this blocks through a restricted line portal, it will always completely block.
if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ) || tcres.zdiff != 0) if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL))
{ // Thing slammed into something; don't let it move now. { // Thing slammed into something; don't let it move now.
thing->height = realheight; thing->height = realheight;
return false; 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 it(pcheck, thing);
FMultiBlockLinesIterator::CheckResult lcres; FMultiBlockLinesIterator::CheckResult lcres;
line_t *ld;
fixed_t thingdropoffz = tm.floorz; fixed_t thingdropoffz = tm.floorz;
//bool onthing = (thingdropoffz != tmdropoffz); //bool onthing = (thingdropoffz != tmdropoffz);