- fixed potential infinite loop in Hexen-style stair builder.

This commit is contained in:
Christoph Oelckers 2022-01-07 00:09:59 +01:00
parent e6403197eb
commit 63fa01205f
4 changed files with 32 additions and 11 deletions

View file

@ -781,7 +781,6 @@ public:
bool IsLinked(sector_t *other, bool ceiling) const; bool IsLinked(sector_t *other, bool ceiling) const;
sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH]
void RemoveForceField(); void RemoveForceField();
int Index() const { return sectornum; } int Index() const { return sectornum; }
@ -1726,6 +1725,8 @@ int GetCeilingLight(const sector_t *);
double GetFriction(const sector_t *self, int plane, double *movefac); double GetFriction(const sector_t *self, int plane, double *movefac);
double HighestCeilingAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr); double HighestCeilingAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr);
double LowestFloorAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr); double LowestFloorAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr);
sector_t* P_NextSpecialSector(sector_t* sect, int type, sector_t* prev);
sector_t* P_NextSpecialSectorVC(sector_t* sect, int type); // uses validcount
inline void sector_t::RemoveForceField() { return ::RemoveForceField(this); } inline void sector_t::RemoveForceField() { return ::RemoveForceField(this); }
inline bool sector_t::PlaneMoving(int pos) { return !!::PlaneMoving(this, pos); } inline bool sector_t::PlaneMoving(int pos) { return !!::PlaneMoving(this, pos); }

View file

@ -40,6 +40,7 @@
#include "r_data/r_interpolate.h" #include "r_data/r_interpolate.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include "vm.h" #include "vm.h"
#include "r_utility.h"
//========================================================================== //==========================================================================
// //
@ -661,6 +662,7 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d
// 1. Find 2-sided line with same sector side[0] (lowest numbered) // 1. Find 2-sided line with same sector side[0] (lowest numbered)
// 2. Other side is the next sector to raise // 2. Other side is the next sector to raise
// 3. Unless already moving, or different texture, then stop building // 3. Unless already moving, or different texture, then stop building
validcount++;
do do
{ {
ok = 0; ok = 0;
@ -668,12 +670,13 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d
if (usespecials & DFloor::stairUseSpecials) if (usespecials & DFloor::stairUseSpecials)
{ {
// [RH] Find the next sector by scanning for Stairs_Special? // [RH] Find the next sector by scanning for Stairs_Special?
tsec = sec->NextSpecialSector ( tsec = P_NextSpecialSectorVC(sec,
sec->special == Stairs_Special1 ? sec->special == Stairs_Special1 ?
Stairs_Special2 : Stairs_Special1, prev); Stairs_Special2 : Stairs_Special1);
if ( (ok = (tsec != NULL)) ) if ( (ok = (tsec != nullptr)) )
{ {
tsec->validcount = validcount;
height += stairstep; height += stairstep;
// if sector's floor already moving, look for another // if sector's floor already moving, look for another

View file

@ -521,7 +521,7 @@ int DPhased::PhaseHelper (sector_t *sector, int index, int light, sector_t *prev
else else
l = Level->CreateThinker<DPhased> (sector, baselevel); l = Level->CreateThinker<DPhased> (sector, baselevel);
int numsteps = PhaseHelper (sector->NextSpecialSector ( int numsteps = PhaseHelper (P_NextSpecialSector (sector,
sector->special == LightSequenceSpecial1 ? sector->special == LightSequenceSpecial1 ?
LightSequenceSpecial2 : LightSequenceSpecial1, prev), LightSequenceSpecial2 : LightSequenceSpecial1, prev),
index + 1, l->m_BaseLevel, sector); index + 1, l->m_BaseLevel, sector);

View file

@ -89,27 +89,44 @@ CUSTOM_CVAR(Int, r_fakecontrast, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
// //
// Returns the next special sector attached to this sector // Returns the next special sector attached to this sector
// with a certain special. // with a certain special.
sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const
sector_t* P_NextSpecialSectorVC(sector_t* sec, int type)
{ {
sector_t* tsec; sector_t* tsec;
for (auto ln : Lines) for (auto ln : sec->Lines)
{ {
if (NULL != (tsec = getNextSector (ln, this)) && if (nullptr != (tsec = getNextSector(ln, sec)) &&
tsec->validcount != validcount &&
tsec->special == type)
{
return tsec;
}
}
return nullptr;
}
sector_t *P_NextSpecialSector (sector_t* sec, int type, sector_t *nogood)
{
sector_t *tsec;
for (auto ln : sec->Lines)
{
if (nullptr != (tsec = getNextSector (ln, sec)) &&
tsec != nogood && tsec != nogood &&
tsec->special == type) tsec->special == type)
{ {
return tsec; return tsec;
} }
} }
return NULL; return nullptr;
} }
DEFINE_ACTION_FUNCTION(_Sector, NextSpecialSector) DEFINE_ACTION_FUNCTION_NATIVE(_Sector, NextSpecialSector, P_NextSpecialSector)
{ {
PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_SELF_STRUCT_PROLOGUE(sector_t);
PARAM_INT(type); PARAM_INT(type);
PARAM_POINTER(nogood, sector_t); PARAM_POINTER(nogood, sector_t);
ACTION_RETURN_POINTER(self->NextSpecialSector(type, nogood)); ACTION_RETURN_POINTER(P_NextSpecialSector(self, type, nogood));
} }
// //