mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- implemented the FMultiBlockThingsIterator and converted P_TeleportMove to use it.
This commit is contained in:
parent
cfbb3bcbb2
commit
58fcd8d742
3 changed files with 196 additions and 14 deletions
|
@ -334,7 +334,7 @@ void P_FindFloorCeiling(AActor *actor, int flags)
|
|||
validcount++;
|
||||
|
||||
FPortalGroupArray grouplist;
|
||||
FMultiBlockLinesIterator mit(grouplist, actor, tmf.x, tmf.y, actor->radius);
|
||||
FMultiBlockLinesIterator mit(grouplist, actor);
|
||||
FMultiBlockLinesIterator::CheckResult cres;
|
||||
|
||||
// if we already have a valid floor/ceiling sector within the current sector,
|
||||
|
@ -420,7 +420,7 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
|
|||
thing->SetZ(z);
|
||||
|
||||
FPortalGroupArray grouplist;
|
||||
FMultiBlockLinesIterator mit(grouplist, thing, tmf.x, tmf.y, thing->radius);
|
||||
FMultiBlockLinesIterator mit(grouplist, x, y, z, thing->height, thing->radius);
|
||||
FMultiBlockLinesIterator::CheckResult cres;
|
||||
|
||||
while (mit.Next(&cres))
|
||||
|
@ -431,11 +431,13 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
|
|||
|
||||
if (tmf.touchmidtex) tmf.dropoffz = tmf.floorz;
|
||||
|
||||
FBlockThingsIterator it2(FBoundingBox(x, y, thing->radius));
|
||||
AActor *th;
|
||||
FMultiBlockThingsIterator mit2(grouplist, x, y, z, thing->height, thing->radius);
|
||||
FMultiBlockThingsIterator::CheckResult cres2;
|
||||
|
||||
while ((th = it2.Next()))
|
||||
while (mit2.Next(&cres2))
|
||||
{
|
||||
AActor *th = cres2.thing;
|
||||
|
||||
if (!(th->flags & MF_SHOOTABLE))
|
||||
continue;
|
||||
|
||||
|
@ -444,7 +446,7 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
|
|||
continue;
|
||||
|
||||
fixed_t blockdist = th->radius + tmf.thing->radius;
|
||||
if (abs(th->X() - tmf.x) >= blockdist || abs(th->Y() - tmf.y) >= blockdist)
|
||||
if (abs(th->X() - cres.position.x) >= blockdist || abs(th->Y() - cres.position.y) >= blockdist)
|
||||
continue;
|
||||
|
||||
if ((th->flags2 | tmf.thing->flags2) & MF2_THRUACTORS)
|
||||
|
|
153
src/p_maputl.cpp
153
src/p_maputl.cpp
|
@ -711,18 +711,34 @@ line_t *FBlockLinesIterator::Next()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkx, fixed_t checky, fixed_t checkradius)
|
||||
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius)
|
||||
: checklist(check)
|
||||
{
|
||||
checkpoint = origin->Pos();
|
||||
if (checkx != FIXED_MAX) checkpoint.x = checkx;
|
||||
if (checky != FIXED_MAX) checkpoint.y = checky;
|
||||
P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
|
||||
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
|
||||
checkpoint.z = checkradius;
|
||||
basegroup = origin->Sector->PortalGroup;
|
||||
Reset();
|
||||
}
|
||||
|
||||
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius)
|
||||
: checklist(check)
|
||||
{
|
||||
checkpoint.x = checkx;
|
||||
checkpoint.y = checky;
|
||||
checkpoint.z = checkz;
|
||||
basegroup = P_PointInSector(checkx, checky)->PortalGroup;
|
||||
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
|
||||
checkpoint.z = checkradius;
|
||||
Reset();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Go up a ceiling portal
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
|
||||
{
|
||||
if (continueup)
|
||||
|
@ -739,6 +755,12 @@ bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
|
|||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Go down a floor portal
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
|
||||
{
|
||||
if (continuedown)
|
||||
|
@ -755,6 +777,12 @@ bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
|
|||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Gets the next line - also manages switching between portal groups
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
||||
{
|
||||
line_t *line = blockIterator.Next();
|
||||
|
@ -808,6 +836,12 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
|||
return Next(item);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// start iterating a new group
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FMultiBlockLinesIterator::startIteratorForGroup(int group)
|
||||
{
|
||||
offset = Displacements(basegroup, group);
|
||||
|
@ -817,6 +851,12 @@ void FMultiBlockLinesIterator::startIteratorForGroup(int group)
|
|||
blockIterator.init(bbox);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Resets the iterator
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FMultiBlockLinesIterator::Reset()
|
||||
{
|
||||
continueup = continueup = true;
|
||||
|
@ -851,8 +891,7 @@ FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int
|
|||
Reset();
|
||||
}
|
||||
|
||||
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
||||
: DynHash(0)
|
||||
void FBlockThingsIterator::init(const FBoundingBox &box)
|
||||
{
|
||||
maxy = GetSafeBlockY(box.Top() - bmaporgy);
|
||||
miny = GetSafeBlockY(box.Bottom() - bmaporgy);
|
||||
|
@ -994,6 +1033,108 @@ AActor *FBlockThingsIterator::Next(bool centeronly)
|
|||
}
|
||||
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FMultiBlockThingsIterator :: FMultiBlockThingsIterator
|
||||
//
|
||||
// An iterator that can check multiple portal groups.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius)
|
||||
: checklist(check)
|
||||
{
|
||||
checkpoint = origin->Pos();
|
||||
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
|
||||
checkpoint.z = checkradius;
|
||||
basegroup = origin->Sector->PortalGroup;
|
||||
Reset();
|
||||
}
|
||||
|
||||
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius)
|
||||
: checklist(check)
|
||||
{
|
||||
checkpoint.x = checkx;
|
||||
checkpoint.y = checky;
|
||||
checkpoint.z = checkz;
|
||||
basegroup = P_PointInSector(checkx, checky)->PortalGroup;
|
||||
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
|
||||
checkpoint.z = checkradius;
|
||||
Reset();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Gets the next line - also manages switching between portal groups
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *item)
|
||||
{
|
||||
AActor *thing = blockIterator.Next();
|
||||
if (thing != NULL)
|
||||
{
|
||||
item->thing = thing;
|
||||
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
|
||||
item->portalflags = portalflags;
|
||||
return true;
|
||||
}
|
||||
bool onlast = unsigned(index + 1) >= checklist.Size();
|
||||
int nextflags = onlast ? 0 : checklist[index + 1] & FPortalGroupArray::FLAT;
|
||||
|
||||
if (onlast)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
index++;
|
||||
startIteratorForGroup(checklist[index] & ~FPortalGroupArray::FLAT);
|
||||
switch (nextflags)
|
||||
{
|
||||
case FPortalGroupArray::UPPER:
|
||||
portalflags = FFCF_NOFLOOR;
|
||||
break;
|
||||
|
||||
case FPortalGroupArray::LOWER:
|
||||
portalflags = FFCF_NOCEILING;
|
||||
break;
|
||||
|
||||
default:
|
||||
portalflags = 0;
|
||||
}
|
||||
|
||||
return Next(item);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// start iterating a new group
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FMultiBlockThingsIterator::startIteratorForGroup(int group)
|
||||
{
|
||||
fixedvec2 offset = Displacements(basegroup, group);
|
||||
offset.x += checkpoint.x;
|
||||
offset.y += checkpoint.y;
|
||||
bbox.setBox(offset.x, offset.y, checkpoint.z);
|
||||
blockIterator.init(bbox);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Resets the iterator
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FMultiBlockThingsIterator::Reset()
|
||||
{
|
||||
index = -1;
|
||||
portalflags = 0;
|
||||
startIteratorForGroup(basegroup);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FPathTraverse :: Intercepts
|
||||
|
|
|
@ -224,7 +224,8 @@ public:
|
|||
int portalflags;
|
||||
};
|
||||
|
||||
FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkx = FIXED_MAX, fixed_t checky = FIXED_MAX, fixed_t checkradius = -1);
|
||||
FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1);
|
||||
FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius);
|
||||
bool Next(CheckResult *item);
|
||||
void Reset();
|
||||
// for stopping group traversal through portals. Only the calling code can decide whether this is needed so this needs to be set from the outside.
|
||||
|
@ -274,14 +275,52 @@ class FBlockThingsIterator
|
|||
FBlockThingsIterator();
|
||||
|
||||
friend class FPathTraverse;
|
||||
friend class FMultiBlockThingsIterator;
|
||||
|
||||
public:
|
||||
FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
|
||||
FBlockThingsIterator(const FBoundingBox &box);
|
||||
FBlockThingsIterator(const FBoundingBox &box)
|
||||
{
|
||||
init(box);
|
||||
}
|
||||
void init(const FBoundingBox &box);
|
||||
AActor *Next(bool centeronly = false);
|
||||
void Reset() { StartBlock(minx, miny); }
|
||||
};
|
||||
|
||||
class FMultiBlockThingsIterator
|
||||
{
|
||||
FPortalGroupArray &checklist;
|
||||
fixedvec3 checkpoint;
|
||||
short basegroup;
|
||||
short portalflags;
|
||||
short index;
|
||||
FBlockThingsIterator blockIterator;
|
||||
FBoundingBox bbox;
|
||||
|
||||
void startIteratorForGroup(int group);
|
||||
|
||||
public:
|
||||
|
||||
struct CheckResult
|
||||
{
|
||||
AActor *thing;
|
||||
fixedvec3 position;
|
||||
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);
|
||||
bool Next(CheckResult *item);
|
||||
void Reset();
|
||||
const FBoundingBox &Box() const
|
||||
{
|
||||
return bbox;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class FPathTraverse
|
||||
{
|
||||
static TArray<intercept_t> intercepts;
|
||||
|
|
Loading…
Reference in a new issue