- more transition to FMultiBlock* iterators:

* removed all code for dealing with z-displacing portals in the iterator loops. This would cause too many problems so I decided to scrap any provisions for allowing interactive portals with z-displacement. They will remain restricted to pure teleporter portals.
 * changed spechit to carry a position along with the special line. If something is activated through an interactive portal this is needed to calculate movement.
 * pass the abovementioned position to CheckForPushSpecial.
 * collect touched portal lines in a second array analogous to spechit.
 * use FMultiBlockThingsIterator in P_TestMobjZ.
This commit is contained in:
Christoph Oelckers 2016-02-21 23:08:51 +01:00
parent ca2fc47fa3
commit 730145d1fc
6 changed files with 67 additions and 53 deletions

View file

@ -83,10 +83,12 @@ bool DBot::Move (ticcmd_t *cmd)
player->mo->movedir = DI_NODIR; player->mo->movedir = DI_NODIR;
good = 0; good = 0;
spechit_t spechit1;
line_t *ld; line_t *ld;
while (spechit.Pop (ld)) while (spechit.Pop (spechit1))
{ {
ld = spechit1.line;
bool tryit = true; bool tryit = true;
if (ld->special == Door_LockedRaise && !P_CheckKeys (player->mo, ld->args[3], false)) if (ld->special == Door_LockedRaise && !P_CheckKeys (player->mo, ld->args[3], false))

View file

@ -612,18 +612,18 @@ bool P_Move (AActor *actor)
// Do NOT simply return false 1/4th of the time (causes monsters to // Do NOT simply return false 1/4th of the time (causes monsters to
// back out when they shouldn't, and creates secondary stickiness). // back out when they shouldn't, and creates secondary stickiness).
line_t *ld; spechit_t spec;
int good = 0; int good = 0;
if (!(actor->flags6 & MF6_NOTRIGGER)) if (!(actor->flags6 & MF6_NOTRIGGER))
{ {
while (spechit.Pop (ld)) while (spechit.Pop (spec))
{ {
// [RH] let monsters push lines, as well as use them // [RH] let monsters push lines, as well as use them
if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (ld, actor, 0, SPAC_Use)) || if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (spec.line, actor, 0, SPAC_Use)) ||
((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_Push))) ((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (spec.line, actor, 0, SPAC_Push)))
{ {
good |= ld == actor->BlockingLine ? 1 : 2; good |= spec.line == actor->BlockingLine ? 1 : 2;
} }
} }
} }

View file

@ -240,7 +240,14 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false)
// if within "tmfloorz - tmceilingz". // if within "tmfloorz - tmceilingz".
extern msecnode_t *sector_list; // phares 3/16/98 extern msecnode_t *sector_list; // phares 3/16/98
extern TArray<line_t *> spechit; struct spechit_t
{
line_t *line;
fixedvec2 refpos;
};
extern TArray<spechit_t> spechit;
extern TArray<spechit_t> portalhit;
bool P_TestMobjLocation (AActor *mobj); bool P_TestMobjLocation (AActor *mobj);

View file

@ -63,7 +63,7 @@ CVAR(Bool, cl_bloodsplats, true, CVAR_ARCHIVE)
CVAR(Int, sv_smartaim, 0, CVAR_ARCHIVE | CVAR_SERVERINFO) CVAR(Int, sv_smartaim, 0, CVAR_ARCHIVE | CVAR_SERVERINFO)
CVAR(Bool, cl_doautoaim, false, CVAR_ARCHIVE) CVAR(Bool, cl_doautoaim, false, CVAR_ARCHIVE)
static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, bool windowcheck); static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, fixedvec2 * posforwindowcheck = NULL);
static void SpawnShootDecal(AActor *t1, const FTraceResults &trace); static void SpawnShootDecal(AActor *t1, const FTraceResults &trace);
static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff, static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff,
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz, bool ffloor = false); fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz, bool ffloor = false);
@ -75,8 +75,8 @@ 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<spechit_t> spechit;
TArray<line_t *> portalhit; TArray<spechit_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
@ -465,8 +465,8 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
{ {
if (!(th->flags3 & thing->flags3 & MF3_DONTOVERLAP)) if (!(th->flags3 & thing->flags3 & MF3_DONTOVERLAP))
{ {
if (z > cres.position.z + th->height || // overhead if (z > th->Top() || // overhead
z + thing->height < cres.position.z) // underneath z + thing->height < th->Z()) // underneath
continue; continue;
} }
} }
@ -560,9 +560,9 @@ void P_PlayerStartStomp(AActor *actor, bool mononly)
if (th->player != NULL && mononly) if (th->player != NULL && mononly)
continue; continue;
if (actor->Z() > cres.position.z + th->height) if (actor->Z() > th->Top())
continue; // overhead continue; // overhead
if (actor->Top() < cres.position.z) if (actor->Top() < th->Z())
continue; // underneath continue; // underneath
P_DamageMobj(th, actor, actor, TELEFRAG_DAMAGE, NAME_Telefrag); P_DamageMobj(th, actor, actor, TELEFRAG_DAMAGE, NAME_Telefrag);
@ -793,7 +793,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
} }
tm.thing->BlockingLine = ld; tm.thing->BlockingLine = ld;
CheckForPushSpecial(ld, 0, tm.thing, false); CheckForPushSpecial(ld, 0, tm.thing);
return false; return false;
} }
@ -824,7 +824,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
} }
tm.thing->BlockingLine = ld; tm.thing->BlockingLine = ld;
// Calculate line side based on the actor's original position, not the new one. // Calculate line side based on the actor's original position, not the new one.
CheckForPushSpecial(ld, P_PointOnLineSide(cres.position.x, cres.position.y, ld), tm.thing, false); CheckForPushSpecial(ld, P_PointOnLineSide(cres.position.x, cres.position.y, ld), tm.thing);
return false; return false;
} }
} }
@ -896,13 +896,18 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
tm.dropoffz = open.lowfloor; tm.dropoffz = open.lowfloor;
// if contacted a special line, add it to the list // if contacted a special line, add it to the list
spechit_t spec;
if (ld->special) if (ld->special)
{ {
spechit.Push(ld); spec.line = ld;
spec.refpos = cres.position;
spechit.Push(spec);
} }
if (ld->portalindex >= 0) if (ld->portalindex >= 0)
{ {
portalhit.Push(ld); spec.line = ld;
spec.refpos = cres.position;
portalhit.Push(spec);
} }
return true; return true;
@ -1038,8 +1043,8 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
(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 (cres.zdiff != 0 && (tm.thing->flags3 & MF3_ISMONSTER) && if ((tm.thing->flags3 & MF3_ISMONSTER) &&
topz >= tm.floorz && topz <= cres.position.z + tm.thing->MaxStepHeight) topz >= tm.floorz && topz <= tm.thing->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
@ -1074,7 +1079,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
if (newdist > olddist) if (newdist > olddist)
{ {
// unblock only if there's already a vertical overlap (or both actors are flagged not to overlap) // 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); unblocking = (tm.thing->Top() > thing->Z() && tm.thing->Z() < topz) || (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP);
} }
} }
} }
@ -1093,7 +1098,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 ((cres.position.z >= topz) || (cres.position.z + tm.thing->height <= thing->Z())) if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z()))
return true; return true;
} }
} }
@ -1109,7 +1114,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 >= cres.position.z && cres.position.z + tm.thing->height >= thing->Z() && topz >= tm.thing->Z() && tm.thing->Top() >= 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
@ -1212,11 +1217,11 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
} }
// Check if it went over / under // Check if it went over / under
if (cres.position.z > thing->Z() + clipheight) if (tm.thing->Z() > thing->Z() + clipheight)
{ // Over thing { // Over thing
return true; return true;
} }
if (cres.position.z + tm.thing->height < thing->Z()) if (tm.thing->Top() < thing->Z())
{ // Under thing { // Under thing
return true; return true;
} }
@ -1367,7 +1372,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.
&& thing->Z() < cres.position.z + tm.thing->height - tm.thing->MaxStepHeight) && thing->Z() < tm.thing->Top() - 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
} }
@ -1641,12 +1646,16 @@ bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj)
return true; return true;
} }
FBlockThingsIterator it(FBoundingBox(actor->X(), actor->Y(), actor->radius)); FPortalGroupArray check;
AActor *thing; FMultiBlockThingsIterator it(check, actor, -1, true);
FMultiBlockThingsIterator::CheckResult cres;
while ((thing = it.Next())) while (it.Next(&cres))
{ {
if (!thing->intersects(actor)) AActor *thing = cres.thing;
fixed_t blockdist = thing->radius + actor->radius;
if (abs(thing->X() - cres.position.x) >= blockdist || abs(thing->Y() - cres.position.y) >= blockdist)
{ {
continue; continue;
} }
@ -1753,18 +1762,18 @@ void P_FakeZMovement(AActor *mo)
// //
//=========================================================================== //===========================================================================
static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, bool windowcheck) static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, fixedvec2 *posforwindowcheck)
{ {
if (line->special && !(mobj->flags6 & MF6_NOTRIGGER)) if (line->special && !(mobj->flags6 & MF6_NOTRIGGER))
{ {
if (windowcheck && !(ib_compatflags & BCOMPATF_NOWINDOWCHECK) && line->backsector != NULL) if (posforwindowcheck && !(ib_compatflags & BCOMPATF_NOWINDOWCHECK) && line->backsector != NULL)
{ // Make sure this line actually blocks us and is not a window { // Make sure this line actually blocks us and is not a window
// or similar construct we are standing inside of. // or similar construct we are standing inside of.
fixedvec3 pos = mobj->PosRelative(line); fixedvec3 pos = mobj->PosRelative(line);
fixed_t fzt = line->frontsector->ceilingplane.ZatPoint(pos); fixed_t fzt = line->frontsector->ceilingplane.ZatPoint(*posforwindowcheck);
fixed_t fzb = line->frontsector->floorplane.ZatPoint(pos); fixed_t fzb = line->frontsector->floorplane.ZatPoint(*posforwindowcheck);
fixed_t bzt = line->backsector->ceilingplane.ZatPoint(pos); fixed_t bzt = line->backsector->ceilingplane.ZatPoint(*posforwindowcheck);
fixed_t bzb = line->backsector->floorplane.ZatPoint(pos); fixed_t bzb = line->backsector->floorplane.ZatPoint(*posforwindowcheck);
if (fzt >= mobj->Top() && bzt >= mobj->Top() && if (fzt >= mobj->Top() && bzt >= mobj->Top() &&
fzb <= mobj->Z() && bzb <= mobj->Z()) fzb <= mobj->Z() && bzb <= mobj->Z())
{ {
@ -1775,8 +1784,8 @@ static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, bool windo
if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
fixed_t ff_bottom = rover->bottom.plane->ZatPoint(pos); fixed_t ff_bottom = rover->bottom.plane->ZatPoint(*posforwindowcheck);
fixed_t ff_top = rover->top.plane->ZatPoint(pos); fixed_t ff_top = rover->top.plane->ZatPoint(*posforwindowcheck);
if (ff_bottom < mobj->Top() && ff_top > mobj->Z()) if (ff_bottom < mobj->Top() && ff_top > mobj->Z())
{ {
@ -2081,12 +2090,13 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
// if any special lines were hit, do the effect // if any special lines were hit, do the effect
if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP)))
{ {
while (spechit.Pop(ld)) spechit_t spec;
while (spechit.Pop(spec))
{ {
fixedvec3 thingpos = thing->PosRelative(ld); line_t *ld = spec.line;
fixedvec3 oldrelpos = PosRelative(oldpos, ld, oldsector); fixedvec3 oldrelpos = PosRelative(oldpos, ld, oldsector);
// see if the line was crossed // see if the line was crossed
side = P_PointOnLineSide(thingpos.x, thingpos.y, ld); side = P_PointOnLineSide(spec.refpos.x, spec.refpos.y, ld);
oldside = P_PointOnLineSide(oldrelpos.x, oldrelpos.y, ld); oldside = P_PointOnLineSide(oldrelpos.x, oldrelpos.y, ld);
if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER)) if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER))
{ {
@ -2185,10 +2195,9 @@ pushline:
while (numSpecHitTemp > 0) while (numSpecHitTemp > 0)
{ {
// see which lines were pushed // see which lines were pushed
ld = spechit[--numSpecHitTemp]; spechit_t &spec = spechit[--numSpecHitTemp];
fixedvec3 pos = thing->PosRelative(ld); side = P_PointOnLineSide(spec.refpos.x, spec.refpos.y, spec.line);
side = P_PointOnLineSide(pos.x, pos.y, ld); CheckForPushSpecial(spec.line, side, thing, &spec.refpos);
CheckForPushSpecial(ld, side, thing, true);
} }
} }
return false; return false;

View file

@ -802,7 +802,6 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
item->position.x = offset.x; item->position.x = offset.x;
item->position.y = offset.y; item->position.y = offset.y;
item->position.z = checkpoint.z; item->position.z = checkpoint.z;
item->zdiff = 0;
item->portalflags = portalflags; item->portalflags = portalflags;
return true; return true;
} }
@ -1055,7 +1054,7 @@ AActor *FBlockThingsIterator::Next(bool centeronly)
// //
//=========================================================================== //===========================================================================
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius) FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius, bool ignorerestricted)
: checklist(check) : checklist(check)
{ {
checkpoint = origin->Pos(); checkpoint = origin->Pos();
@ -1065,7 +1064,7 @@ FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, A
Reset(); Reset();
} }
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius) FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted)
: checklist(check) : checklist(check)
{ {
checkpoint.x = checkx; checkpoint.x = checkx;
@ -1090,7 +1089,6 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
{ {
item->thing = thing; item->thing = thing;
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup); item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
item->zdiff = 0;
item->portalflags = portalflags; item->portalflags = portalflags;
return true; return true;
} }

View file

@ -223,7 +223,6 @@ public:
{ {
line_t *line; line_t *line;
fixedvec3 position; fixedvec3 position;
fixed_t zdiff;
int portalflags; int portalflags;
}; };
@ -309,12 +308,11 @@ public:
{ {
AActor *thing; AActor *thing;
fixedvec3 position; fixedvec3 position;
fixed_t zdiff;
int portalflags; int portalflags;
}; };
FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1); FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1, bool ignorerestricted = false);
FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius); FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted = false);
bool Next(CheckResult *item); bool Next(CheckResult *item);
void Reset(); void Reset();
const FBoundingBox &Box() const const FBoundingBox &Box() const