mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +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++;
|
validcount++;
|
||||||
|
|
||||||
FPortalGroupArray grouplist;
|
FPortalGroupArray grouplist;
|
||||||
FMultiBlockLinesIterator mit(grouplist, actor, tmf.x, tmf.y, actor->radius);
|
FMultiBlockLinesIterator mit(grouplist, actor);
|
||||||
FMultiBlockLinesIterator::CheckResult cres;
|
FMultiBlockLinesIterator::CheckResult cres;
|
||||||
|
|
||||||
// if we already have a valid floor/ceiling sector within the current sector,
|
// 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);
|
thing->SetZ(z);
|
||||||
|
|
||||||
FPortalGroupArray grouplist;
|
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;
|
FMultiBlockLinesIterator::CheckResult cres;
|
||||||
|
|
||||||
while (mit.Next(&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;
|
if (tmf.touchmidtex) tmf.dropoffz = tmf.floorz;
|
||||||
|
|
||||||
FBlockThingsIterator it2(FBoundingBox(x, y, thing->radius));
|
FMultiBlockThingsIterator mit2(grouplist, x, y, z, thing->height, thing->radius);
|
||||||
AActor *th;
|
FMultiBlockThingsIterator::CheckResult cres2;
|
||||||
|
|
||||||
while ((th = it2.Next()))
|
while (mit2.Next(&cres2))
|
||||||
{
|
{
|
||||||
|
AActor *th = cres2.thing;
|
||||||
|
|
||||||
if (!(th->flags & MF_SHOOTABLE))
|
if (!(th->flags & MF_SHOOTABLE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -444,7 +446,7 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fixed_t blockdist = th->radius + tmf.thing->radius;
|
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;
|
continue;
|
||||||
|
|
||||||
if ((th->flags2 | tmf.thing->flags2) & MF2_THRUACTORS)
|
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)
|
: checklist(check)
|
||||||
{
|
{
|
||||||
checkpoint = origin->Pos();
|
checkpoint = origin->Pos();
|
||||||
if (checkx != FIXED_MAX) checkpoint.x = checkx;
|
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
|
||||||
if (checky != FIXED_MAX) checkpoint.y = checky;
|
|
||||||
P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
|
|
||||||
checkpoint.z = checkradius;
|
checkpoint.z = checkradius;
|
||||||
basegroup = origin->Sector->PortalGroup;
|
basegroup = origin->Sector->PortalGroup;
|
||||||
Reset();
|
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)
|
bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
|
||||||
{
|
{
|
||||||
if (continueup)
|
if (continueup)
|
||||||
|
@ -739,6 +755,12 @@ bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Go down a floor portal
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
|
bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
|
||||||
{
|
{
|
||||||
if (continuedown)
|
if (continuedown)
|
||||||
|
@ -755,6 +777,12 @@ bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Gets the next line - also manages switching between portal groups
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
||||||
{
|
{
|
||||||
line_t *line = blockIterator.Next();
|
line_t *line = blockIterator.Next();
|
||||||
|
@ -808,6 +836,12 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
||||||
return Next(item);
|
return Next(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// start iterating a new group
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
void FMultiBlockLinesIterator::startIteratorForGroup(int group)
|
void FMultiBlockLinesIterator::startIteratorForGroup(int group)
|
||||||
{
|
{
|
||||||
offset = Displacements(basegroup, group);
|
offset = Displacements(basegroup, group);
|
||||||
|
@ -817,6 +851,12 @@ void FMultiBlockLinesIterator::startIteratorForGroup(int group)
|
||||||
blockIterator.init(bbox);
|
blockIterator.init(bbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Resets the iterator
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
void FMultiBlockLinesIterator::Reset()
|
void FMultiBlockLinesIterator::Reset()
|
||||||
{
|
{
|
||||||
continueup = continueup = true;
|
continueup = continueup = true;
|
||||||
|
@ -851,8 +891,7 @@ FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
void FBlockThingsIterator::init(const FBoundingBox &box)
|
||||||
: DynHash(0)
|
|
||||||
{
|
{
|
||||||
maxy = GetSafeBlockY(box.Top() - bmaporgy);
|
maxy = GetSafeBlockY(box.Top() - bmaporgy);
|
||||||
miny = GetSafeBlockY(box.Bottom() - 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
|
// FPathTraverse :: Intercepts
|
||||||
|
|
|
@ -224,7 +224,8 @@ public:
|
||||||
int portalflags;
|
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);
|
bool Next(CheckResult *item);
|
||||||
void Reset();
|
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.
|
// 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();
|
FBlockThingsIterator();
|
||||||
|
|
||||||
friend class FPathTraverse;
|
friend class FPathTraverse;
|
||||||
|
friend class FMultiBlockThingsIterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
|
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);
|
AActor *Next(bool centeronly = false);
|
||||||
void Reset() { StartBlock(minx, miny); }
|
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
|
class FPathTraverse
|
||||||
{
|
{
|
||||||
static TArray<intercept_t> intercepts;
|
static TArray<intercept_t> intercepts;
|
||||||
|
|
Loading…
Reference in a new issue