- 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;
good = 0;
spechit_t spechit1;
line_t *ld;
while (spechit.Pop (ld))
while (spechit.Pop (spechit1))
{
ld = spechit1.line;
bool tryit = true;
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
// back out when they shouldn't, and creates secondary stickiness).
line_t *ld;
spechit_t spec;
int good = 0;
if (!(actor->flags6 & MF6_NOTRIGGER))
{
while (spechit.Pop (ld))
while (spechit.Pop (spec))
{
// [RH] let monsters push lines, as well as use them
if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (ld, actor, 0, SPAC_Use)) ||
((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_Push)))
if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (spec.line, actor, 0, SPAC_Use)) ||
((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".
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);

View file

@ -63,7 +63,7 @@ CVAR(Bool, cl_bloodsplats, true, CVAR_ARCHIVE)
CVAR(Int, sv_smartaim, 0, CVAR_ARCHIVE | CVAR_SERVERINFO)
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 SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff,
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,
// but don't process them until the move is proven valid
TArray<line_t *> spechit;
TArray<line_t *> portalhit;
TArray<spechit_t> spechit;
TArray<spechit_t> portalhit;
// Temporary holder for thing_sectorlist threads
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 (z > cres.position.z + th->height || // overhead
z + thing->height < cres.position.z) // underneath
if (z > th->Top() || // overhead
z + thing->height < th->Z()) // underneath
continue;
}
}
@ -560,9 +560,9 @@ void P_PlayerStartStomp(AActor *actor, bool mononly)
if (th->player != NULL && mononly)
continue;
if (actor->Z() > cres.position.z + th->height)
if (actor->Z() > th->Top())
continue; // overhead
if (actor->Top() < cres.position.z)
if (actor->Top() < th->Z())
continue; // underneath
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);
}
tm.thing->BlockingLine = ld;
CheckForPushSpecial(ld, 0, tm.thing, false);
CheckForPushSpecial(ld, 0, tm.thing);
return false;
}
@ -824,7 +824,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
}
tm.thing->BlockingLine = ld;
// 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;
}
}
@ -896,13 +896,18 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
tm.dropoffz = open.lowfloor;
// if contacted a special line, add it to the list
spechit_t spec;
if (ld->special)
{
spechit.Push(ld);
spec.line = ld;
spec.refpos = cres.position;
spechit.Push(spec);
}
if (ld->portalindex >= 0)
{
portalhit.Push(ld);
spec.line = ld;
spec.refpos = cres.position;
portalhit.Push(spec);
}
return true;
@ -1038,8 +1043,8 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
(thing->flags & MF_SOLID) && (thing->flags4 & MF4_ACTLIKEBRIDGE))
{
// [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)
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
@ -1074,7 +1079,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
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);
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
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;
}
}
@ -1109,7 +1114,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 >= 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
(thing->master != tm.thing && tm.thing->master != thing))
// 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
if (cres.position.z > thing->Z() + clipheight)
if (tm.thing->Z() > thing->Z() + clipheight)
{ // Over thing
return true;
}
if (cres.position.z + tm.thing->height < thing->Z())
if (tm.thing->Top() < thing->Z())
{ // Under thing
return true;
}
@ -1367,7 +1372,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.
&& 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
P_TouchSpecialThing(thing, tm.thing); // can remove thing
}
@ -1641,12 +1646,16 @@ bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj)
return true;
}
FBlockThingsIterator it(FBoundingBox(actor->X(), actor->Y(), actor->radius));
AActor *thing;
FPortalGroupArray check;
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;
}
@ -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 (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
// or similar construct we are standing inside of.
fixedvec3 pos = mobj->PosRelative(line);
fixed_t fzt = line->frontsector->ceilingplane.ZatPoint(pos);
fixed_t fzb = line->frontsector->floorplane.ZatPoint(pos);
fixed_t bzt = line->backsector->ceilingplane.ZatPoint(pos);
fixed_t bzb = line->backsector->floorplane.ZatPoint(pos);
fixed_t fzt = line->frontsector->ceilingplane.ZatPoint(*posforwindowcheck);
fixed_t fzb = line->frontsector->floorplane.ZatPoint(*posforwindowcheck);
fixed_t bzt = line->backsector->ceilingplane.ZatPoint(*posforwindowcheck);
fixed_t bzb = line->backsector->floorplane.ZatPoint(*posforwindowcheck);
if (fzt >= mobj->Top() && bzt >= mobj->Top() &&
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;
fixed_t ff_bottom = rover->bottom.plane->ZatPoint(pos);
fixed_t ff_top = rover->top.plane->ZatPoint(pos);
fixed_t ff_bottom = rover->bottom.plane->ZatPoint(*posforwindowcheck);
fixed_t ff_top = rover->top.plane->ZatPoint(*posforwindowcheck);
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 (!(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);
// 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);
if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER))
{
@ -2185,10 +2195,9 @@ pushline:
while (numSpecHitTemp > 0)
{
// see which lines were pushed
ld = spechit[--numSpecHitTemp];
fixedvec3 pos = thing->PosRelative(ld);
side = P_PointOnLineSide(pos.x, pos.y, ld);
CheckForPushSpecial(ld, side, thing, true);
spechit_t &spec = spechit[--numSpecHitTemp];
side = P_PointOnLineSide(spec.refpos.x, spec.refpos.y, spec.line);
CheckForPushSpecial(spec.line, side, thing, &spec.refpos);
}
}
return false;

View file

@ -802,7 +802,6 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
item->position.x = offset.x;
item->position.y = offset.y;
item->position.z = checkpoint.z;
item->zdiff = 0;
item->portalflags = portalflags;
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)
{
checkpoint = origin->Pos();
@ -1065,7 +1064,7 @@ FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, A
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)
{
checkpoint.x = checkx;
@ -1090,7 +1089,6 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
{
item->thing = thing;
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
item->zdiff = 0;
item->portalflags = portalflags;
return true;
}

View file

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