- replaced P_FindSectorFromTag with an FSectorTagIterator class.

This is done to encapsulate the gory details of tag search in one place so that the implementation of multiple tags per sector remains contained to a few isolated spots in the code.
This also moves the special 'tag == 0 -> activate backsector' handling into the iterator class.
This commit is contained in:
Christoph Oelckers 2015-04-14 22:39:57 +02:00
parent 7b4f950330
commit 425e5b9ffc
18 changed files with 356 additions and 331 deletions

View File

@ -312,18 +312,24 @@ static int T_GetPlayerNum(const svalue_t &arg)
// sectors directly by passing a negative value
//
//==========================================================================
int T_FindSectorFromTag(int tagnum,int startsector)
class FSSectorTagIterator : public FSectorTagIterator
{
if (tagnum<=0)
public:
FSSectorTagIterator(int tag)
: FSectorTagIterator(tag)
{
if (startsector<0)
if (tag < 0)
{
if (tagnum==-32768) return 0;
if (-tagnum<numsectors) return -tagnum;
searchtag = INT_MIN;
start = tag == -32768? 0 : -tag < numsectors? -tag : -1;
}
return -1;
}
return P_FindSectorFromTag(tagnum,startsector);
};
inline int T_FindFirstSectorFromTag(int tagnum)
{
FSSectorTagIterator it(tagnum);
return it.Next();
}
@ -1536,7 +1542,8 @@ void FParser::SF_StartSectorSound(void)
tagnum = intvalue(t_argv[0]);
int i=-1;
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sector = &sectors[i];
S_Sound(sector, CHAN_BODY, T_FindSound(stringvalue(t_argv[1])), 1.0f, ATTN_NORM);
@ -1595,7 +1602,8 @@ void FParser::SF_FloorHeight(void)
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
if (sectors[i].floordata) continue; // don't move floors that are active!
@ -1612,7 +1620,7 @@ void FParser::SF_FloorHeight(void)
}
else
{
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
script_error("sector not found with tagnum %i\n", tagnum);
@ -1671,7 +1679,8 @@ void FParser::SF_MoveFloor(void)
// move all sectors with tag
while ((secnum = T_FindSectorFromTag(tagnum, secnum)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
// Don't start a second thinker on the same floor
@ -1733,7 +1742,8 @@ void FParser::SF_CeilingHeight(void)
dest = fixedvalue(t_argv[1]);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
if (sectors[i].ceilingdata) continue; // don't move ceilings that are active!
@ -1750,7 +1760,7 @@ void FParser::SF_CeilingHeight(void)
}
else
{
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
script_error("sector not found with tagnum %i\n", tagnum);
@ -1823,7 +1833,8 @@ void FParser::SF_MoveCeiling(void)
silent=t_argc>4 ? intvalue(t_argv[4]):1;
// move all sectors with tag
while ((secnum = T_FindSectorFromTag(tagnum, secnum)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
@ -1851,7 +1862,7 @@ void FParser::SF_LightLevel(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
@ -1865,7 +1876,8 @@ void FParser::SF_LightLevel(void)
int i = -1;
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].SetLightLevel(intvalue(t_argv[1]));
}
@ -1984,7 +1996,8 @@ void FParser::SF_FadeLight(void)
destlevel = intvalue(t_argv[1]);
speed = t_argc>2 ? intvalue(t_argv[2]) : 1;
for (i = -1; (i = P_FindSectorFromTag(sectag,i)) >= 0;)
FSectorTagIterator it(sectag);
while ((i = it.Next()) >= 0)
{
if (!sectors[i].lightingdata) new DLightLevel(&sectors[i],destlevel,speed);
}
@ -2006,7 +2019,7 @@ void FParser::SF_FloorTexture(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -2019,7 +2032,8 @@ void FParser::SF_FloorTexture(void)
FTextureID picnum = TexMan.GetTexture(t_argv[1].string, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].SetTexture(sector_t::floor, picnum);
}
@ -2057,7 +2071,7 @@ void FParser::SF_SectorColormap(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -2068,7 +2082,8 @@ void FParser::SF_SectorColormap(void)
{
DWORD cm = R_ColormapNumForName(t_argv[1].value.s);
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].midmap=cm;
sectors[i].heightsec=&sectors[i];
@ -2094,7 +2109,7 @@ void FParser::SF_CeilingTexture(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -2107,7 +2122,8 @@ void FParser::SF_CeilingTexture(void)
FTextureID picnum = TexMan.GetTexture(t_argv[1].string, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].SetTexture(sector_t::ceiling, picnum);
}
@ -4201,7 +4217,7 @@ void FParser::SF_SetColor(void)
{
tagnum = intvalue(t_argv[0]);
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{
@ -4222,7 +4238,8 @@ void FParser::SF_SetColor(void)
else return;
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].ColorMap = GetSpecialLights (color, sectors[i].ColorMap->Fade, 0);
}
@ -4314,7 +4331,7 @@ void FParser::SF_SectorType(void)
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindSectorFromTag(tagnum, -1);
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
@ -4327,7 +4344,8 @@ void FParser::SF_SectorType(void)
int spec = intvalue(t_argv[1]);
// set all sectors with tag
while ((i = T_FindSectorFromTag(tagnum, i)) >= 0)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].special = spec;
}
@ -4386,7 +4404,9 @@ void FParser::SF_ChangeTag()
{
if (CheckArgs(2))
{
for (int secnum = -1; (secnum = P_FindSectorFromTag (t_argv[0].value.i, secnum)) >= 0; )
FSectorTagIterator it(t_argv[0].value.i);
int secnum;
while ((secnum = it.Next()) >= 0)
{
sectors[secnum].ClearTags();
sectors[secnum].SetMainTag(t_argv[1].value.i);

View File

@ -452,9 +452,9 @@ bool DFraggleThinker::wait_finished(DRunningScript *script)
case wt_tagwait:
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag(script->wait_data, secnum)) >= 0)
int secnum;
FSectorTagIterator itr(script->wait_data);
while ((secnum = itr.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if(sec->floordata || sec->ceilingdata || sec->lightingdata)

View File

@ -119,7 +119,9 @@ void ASkyCamCompat::BeginPlay ()
// Finally, skyboxify all tagged sectors
// This involves changing their texture to the sky flat, because while
// EE works with any texture for its skybox portals, ZDoom doesn't.
for (int secnum =-1; (secnum = P_FindSectorFromTag (skybox_id, secnum)) != -1; )
FSectorTagIterator it(skybox_id);
int secnum;
while ((secnum = it.Next()) >= 0)
{
// plane: 0=floor, 1=ceiling, 2=both
if (refline->args[2] == 1 || refline->args[2] == 2)

View File

@ -220,7 +220,8 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha)
int tag=line->args[0];
sector_t * sec = line->frontsector, * ss;
for (s=-1; (s = P_FindSectorFromTag(tag,s)) >= 0;)
FSectorTagIterator it(tag);
while ((s = it.Next()) >= 0)
{
ss=&sectors[s];

View File

@ -157,7 +157,9 @@ void P_Attach3dMidtexLinesToSector(sector_t *sector, int lineid, int tag, bool c
}
else
{
for(int sec = -1; (sec = P_FindSectorFromTag(tag, sec)) >= 0; )
FSectorTagIterator it(tag);
int sec;
while ((sec = it.Next()) >= 0)
{
for (int line = 0; line < sectors[sec].linecount; line ++)
{

View File

@ -1341,7 +1341,7 @@ DPlaneWatcher::DPlaneWatcher (AActor *it, line_t *line, int lineSide, bool ceili
{
int secnum;
secnum = P_FindSectorFromTag (tag, -1);
secnum = P_FindFirstSectorFromTag (tag);
if (secnum >= 0)
{
secplane_t plane;
@ -3268,7 +3268,8 @@ void DLevelScript::ChangeFlat (int tag, int name, bool floorOrCeiling)
flat = TexMan.GetTexture (flatname, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
int pos = floorOrCeiling? sector_t::ceiling : sector_t::floor;
sectors[secnum].SetTexture(pos, flat);
@ -4839,10 +4840,10 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
return 0; // Not implemented yet
case ACSF_GetSectorUDMFInt:
return GetUDMFInt(UDMF_Sector, P_FindSectorFromTag(args[0], -1), FBehavior::StaticLookupString(args[1]));
return GetUDMFInt(UDMF_Sector, P_FindFirstSectorFromTag(args[0]), FBehavior::StaticLookupString(args[1]));
case ACSF_GetSectorUDMFFixed:
return GetUDMFFixed(UDMF_Sector, P_FindSectorFromTag(args[0], -1), FBehavior::StaticLookupString(args[1]));
return GetUDMFFixed(UDMF_Sector, P_FindFirstSectorFromTag(args[0]), FBehavior::StaticLookupString(args[1]));
case ACSF_GetSideUDMFInt:
return GetUDMFInt(UDMF_Side, SideFromID(args[0], args[1]), FBehavior::StaticLookupString(args[2]));
@ -5169,11 +5170,11 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
int space = args[2] < CHAN_FLOOR || args[2] > CHAN_INTERIOR ? CHAN_FULLHEIGHT : args[2];
if (seqname != NULL)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
FSectorTagIterator it(args[0]);
int s;
while ((s = it.Next()) >= 0)
{
SN_StartSequence(&sectors[secnum], args[2], seqname, 0);
SN_StartSequence(&sectors[s], args[2], seqname, 0);
}
}
}
@ -5952,11 +5953,13 @@ int DLevelScript::RunScript ()
// Wait for tagged sector(s) to go inactive, then enter
// state running
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (statedata, secnum)) >= 0)
int secnum;
FSectorTagIterator it(statedata);
while ((secnum = it.Next()) >= 0)
{
if (sectors[secnum].floordata || sectors[secnum].ceilingdata)
return resultValue;
}
// If we got here, none of the tagged sectors were busy
state = SCRIPT_Running;
@ -8518,7 +8521,7 @@ scriptwait:
fixed_t z = 0;
if (tag != 0)
secnum = P_FindSectorFromTag (tag, -1);
secnum = P_FindFirstSectorFromTag (tag);
else
secnum = int(P_PointInSector (x, y) - sectors);
@ -8540,7 +8543,7 @@ scriptwait:
case PCD_GETSECTORLIGHTLEVEL:
{
int secnum = P_FindSectorFromTag (STACK(1), -1);
int secnum = P_FindFirstSectorFromTag (STACK(1));
int z = -1;
if (secnum >= 0)

View File

@ -510,9 +510,9 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
P_ActivateInStasisCeiling (tag);
}
secnum = -1;
// affects all sectors with the same tag as the linedef
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
rtn |= !!DCeiling::Create(&sectors[secnum], type, line, tag, speed, speed2, height, crush, silent, change, hexencrush);
}

View File

@ -484,8 +484,8 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
else
{ // [RH] Remote door
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
// if the ceiling is already moving, don't start the door action
@ -812,7 +812,8 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay)
return false;
}
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
if (sec->ceilingdata != NULL)

View File

@ -290,28 +290,13 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
rtn = false;
// check if a manual trigger; if so do just the sector on the backside
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
secnum = (int)(sec-sectors);
goto manual_floor;
}
secnum = -1;
while (tag && (secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag, line);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
manual_floor:
// ALREADY MOVING? IF SO, KEEP GOING...
if (sec->PlaneMoving(sector_t::floor))
{
// There was a test for 0/non-0 here, supposed to prevent 0-tags from executing "continue" and searching for unrelated sectors
// Unfortunately, the condition had been reversed, so that searches for tag-0 would continue,
// while numbered tags would abort (return false, even if some floors have been successfully triggered)
// All occurences of the condition (faulty or not) have been replaced by a looping condition: Looping only occurs if we're looking for a non-0 tag.
continue;
}
@ -545,9 +530,9 @@ manual_floor:
bool EV_FloorCrushStop (int tag)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = sectors + secnum;
@ -562,21 +547,6 @@ bool EV_FloorCrushStop (int tag)
return true;
}
//==========================================================================
//
// Linear tag search to emulate stair building from Doom.exe
//
//==========================================================================
static int P_FindSectorFromTagLinear (int tag, int start)
{
for (int i=start+1;i<numsectors;i++)
{
if (sectors[i].HasTag(tag)) return i;
}
return -1;
}
//==========================================================================
//
// BUILD A STAIRCASE!
@ -591,7 +561,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
fixed_t stairsize, fixed_t speed, int delay, int reset, int igntxt,
int usespecials)
{
int secnum;
int secnum = -1;
int osecnum; //jff 3/4/98 save old loop index
int height;
fixed_t stairstep;
@ -607,44 +577,27 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
sector_t* prev = NULL;
DFloor* floor;
bool manual = false;
if (speed == 0)
return false;
persteptime = FixedDiv (stairsize, speed) >> FRACBITS;
int (* FindSector) (int tag, int start) =
(i_compatflags & COMPATF_STAIRINDEX)? P_FindSectorFromTagLinear : P_FindSectorFromTag;
// check if a manual trigger, if so do just the sector on the backside
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
secnum = (int)(sec-sectors);
manual = true;
goto manual_stair;
}
FSectorTagIterator itr(tag, line);
// The compatibility mode doesn't work with a hashing algorithm.
// It needs the original linear search method. This was broken in Boom.
secnum = -1;
while ((secnum = FindSector (tag, secnum)) >= 0)
bool compatible = tag != 0 && (i_compatflags & COMPATF_STAIRINDEX);
while ((secnum = itr.NextCompat(compatible, secnum)) >= 0)
{
sec = &sectors[secnum];
manual_stair:
// ALREADY MOVING? IF SO, KEEP GOING...
//jff 2/26/98 add special lockout condition to wait for entire
//staircase to build before retriggering
if (sec->PlaneMoving(sector_t::floor) || sec->stairlock)
{
if (!manual)
continue;
else
return rtn;
continue;
}
// new floor thinker
@ -781,14 +734,6 @@ manual_stair:
// [RH] make sure the first sector doesn't point to a previous one, otherwise
// it can infinite loop when the first sector stops moving.
sectors[osecnum].prevsec = -1;
if (manual)
{
return rtn;
}
if (!(i_compatflags & COMPATF_STAIRINDEX))
{
secnum = osecnum; //jff 3/4/98 restore loop index
}
}
return rtn;
}
@ -811,21 +756,13 @@ bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed)
vertex_t* spot;
fixed_t height;
secnum = -1;
rtn = false;
if (tag == 0)
{
if (!line || !(s1 = line->backsector))
return rtn;
goto manual_donut;
}
while (tag && (secnum = P_FindSectorFromTag(tag,secnum)) >= 0)
FSectorTagIterator itr(tag, line);
while ((secnum = itr.Next()) >= 0)
{
s1 = &sectors[secnum]; // s1 is pillar's sector
manual_donut:
// ALREADY MOVING? IF SO, KEEP GOING...
if (s1->PlaneMoving(sector_t::floor))
continue; // safe now, because we check that tag is non-0 in the looping condition [fdari]
@ -1042,19 +979,12 @@ bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype,
secnum = -1;
rtn = false;
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
goto manual_elevator;
}
FSectorTagIterator itr(tag, line);
// act on all sectors with the same tag as the triggering linedef
while (tag && (secnum = P_FindSectorFromTag (tag, secnum)) >= 0) // never loop for a non-0 tag (condition moved to beginning of loop) [FDARI]
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
manual_elevator:
// If either floor or ceiling is already activated, skip it
if (sec->PlaneMoving(sector_t::floor) || sec->ceilingdata) //jff 2/22/98
continue; // the loop used to break at the end if tag were 0, but would miss that step if "continue" occured [FDARI]
@ -1142,10 +1072,10 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
sector_t *sec;
sector_t *secm;
secnum = -1;
rtn = false;
// change all sectors with the same tag as the linedef
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sec = &sectors[secnum];
@ -1374,20 +1304,12 @@ bool EV_StartWaggle (int tag, line_t *line, int height, int speed, int offset,
bool retCode;
retCode = false;
sectorIndex = -1;
if (tag == 0)
{
if (!line || !(sector = line->backsector))
return retCode;
goto manual_waggle;
}
FSectorTagIterator itr(tag, line);
while (tag && (sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
while ((sectorIndex = itr.Next()) >= 0)
{
sector = &sectors[sectorIndex];
manual_waggle:
if ((!ceiling && sector->PlaneMoving(sector_t::floor)) ||
(ceiling && sector->PlaneMoving(sector_t::ceiling)))
{ // Already busy with another thinker

View File

@ -189,9 +189,8 @@ DFlicker::DFlicker (sector_t *sector, int upper, int lower)
void EV_StartLightFlickering (int tag, int upper, int lower)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
new DFlicker (&sectors[secnum], upper, lower);
}
@ -359,9 +358,8 @@ DStrobe::DStrobe (sector_t *sector, int utics, int ltics, bool inSync)
void EV_StartLightStrobing (int tag, int upper, int lower, int utics, int ltics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)
@ -374,9 +372,8 @@ void EV_StartLightStrobing (int tag, int upper, int lower, int utics, int ltics)
void EV_StartLightStrobing (int tag, int utics, int ltics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)
@ -396,16 +393,14 @@ void EV_StartLightStrobing (int tag, int utics, int ltics)
void EV_TurnTagLightsOff (int tag)
{
int i;
int secnum;
// [RH] Don't do a linear search
for (secnum = -1; (secnum = P_FindSectorFromTag (tag, secnum)) >= 0; )
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sector = sectors + secnum;
int min = sector->lightlevel;
for (i = 0; i < sector->linecount; i++)
for (int i = 0; i < sector->linecount; i++)
{
sector_t *tsec = getNextSector (sector->lines[i],sector);
if (!tsec)
@ -427,10 +422,9 @@ void EV_TurnTagLightsOff (int tag)
void EV_LightTurnOn (int tag, int bright)
{
int secnum = -1;
// [RH] Don't do a linear search
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sector = sectors + secnum;
int tbright = bright; //jff 5/17/98 search for maximum PER sector
@ -480,15 +474,14 @@ void EV_LightTurnOn (int tag, int bright)
void EV_LightTurnOnPartway (int tag, fixed_t frac)
{
int i;
frac = clamp<fixed_t> (frac, 0, FRACUNIT);
// Search all sectors for ones with same tag as activating line
i = -1;
while ((i = P_FindSectorFromTag (tag, i)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *temp, *sector = sectors + i;
sector_t *temp, *sector = &sectors[secnum];
int j, bright = 0, min = sector->lightlevel;
for (j = 0; j < sector->linecount; ++j)
@ -520,9 +513,9 @@ void EV_LightTurnOnPartway (int tag, fixed_t frac)
void EV_LightChange (int tag, int value)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
int secnum;
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sectors[secnum].SetLightLevel(sectors[secnum].lightlevel + value);
}
@ -681,8 +674,8 @@ void EV_StartLightGlowing (int tag, int upper, int lower, int tics)
lower = temp;
}
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)
@ -701,9 +694,8 @@ void EV_StartLightGlowing (int tag, int upper, int lower, int tics)
void EV_StartLightFading (int tag, int value, int tics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
FSectorTagIterator it(tag);
while ((secnum = it.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
if (sec->lightingdata)

View File

@ -316,7 +316,9 @@ bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype)
if (movetype > 0)
{
for(int sec = -1; (sec = P_FindSectorFromTag(tag, sec)) >= 0; )
int sec;
FSectorTagIterator itr(tag);
while ((sec = itr.Next()) >= 0)
{
// Don't attach to self!
if (control != &sectors[sec])

View File

@ -1914,9 +1914,9 @@ FUNC(LS_Sector_ChangeSound)
if (!arg0)
return false;
secNum = -1;
rtn = false;
while ((secNum = P_FindSectorFromTag (arg0, secNum)) >= 0)
FSectorTagIterator itr(arg0);
while ((secNum = itr.Next()) >= 0)
{
sectors[secNum].seqType = arg1;
rtn = true;
@ -1933,9 +1933,9 @@ FUNC(LS_Sector_ChangeFlags)
if (!arg0)
return false;
secNum = -1;
rtn = false;
while ((secNum = P_FindSectorFromTag (arg0, secNum)) >= 0)
FSectorTagIterator itr(arg0);
while ((secNum = itr.Next()) >= 0)
{
sectors[secNum].Flags = (sectors[secNum].Flags | arg1) & ~arg2;
rtn = true;
@ -1969,10 +1969,11 @@ void AdjustPusher (int tag, int magnitude, int angle, DPusher::EPusher type)
}
size_t numcollected = Collection.Size ();
int secnum = -1;
int secnum;
// Now create pushers for any sectors that don't already have them.
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
while ((secnum = itr.Next()) >= 0)
{
unsigned int i;
for (i = 0; i < numcollected; i++)
@ -2020,9 +2021,9 @@ FUNC(LS_Sector_SetTranslucent)
{
if (arg0 != 0)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
int secnum;
FSectorTagIterator itr(arg0);
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetAlpha(arg1, Scale(arg2, OPAQUE, 255));
sectors[secnum].ChangeFlags(arg1, ~PLANEF_ADDITIVE, arg3? PLANEF_ADDITIVE:0);
@ -2037,7 +2038,7 @@ FUNC(LS_Sector_SetLink)
{
if (arg0 != 0) // control tag == 0 is for static initialization and must not be handled here
{
int control = P_FindSectorFromTag(arg0, -1);
int control = P_FindFirstSectorFromTag(arg0);
if (control >= 0)
{
return P_AddSectorLinks(&sectors[control], arg1, arg2, arg3);
@ -2181,7 +2182,8 @@ static void SetScroller (int tag, DScroller::EScrollType type, fixed_t dx, fixed
}
// Need to create scrollers for the sector(s)
for (i = -1; (i = P_FindSectorFromTag (tag, i)) >= 0; )
FSectorTagIterator itr(tag);
while ((i = itr.Next()) >= 0)
{
new DScroller (type, dx, dy, -1, i, 0);
}
@ -2240,8 +2242,10 @@ FUNC(LS_Sector_SetDamage)
// problems by adding an unwanted constructor.
// Since it doesn't really matter whether the type is translated
// here or in P_PlayerInSpecialSector I think it's the best solution.
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0) {
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].damage = arg1;
sectors[secnum].mod = arg2;
}
@ -2251,14 +2255,15 @@ FUNC(LS_Sector_SetDamage)
FUNC(LS_Sector_SetGravity)
// Sector_SetGravity (tag, intpart, fracpart)
{
int secnum = -1;
float gravity;
if (arg2 > 99)
arg2 = 99;
gravity = (float)arg1 + (float)arg2 * 0.01f;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
sectors[secnum].gravity = gravity;
return true;
@ -2267,9 +2272,9 @@ FUNC(LS_Sector_SetGravity)
FUNC(LS_Sector_SetColor)
// Sector_SetColor (tag, r, g, b, desaturate)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetColor(arg1, arg2, arg3, arg4);
}
@ -2280,9 +2285,9 @@ FUNC(LS_Sector_SetColor)
FUNC(LS_Sector_SetFade)
// Sector_SetFade (tag, r, g, b)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetFade(arg1, arg2, arg3);
}
@ -2292,11 +2297,12 @@ FUNC(LS_Sector_SetFade)
FUNC(LS_Sector_SetCeilingPanning)
// Sector_SetCeilingPanning (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xofs = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yofs = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetXOffset(sector_t::ceiling, xofs);
sectors[secnum].SetYOffset(sector_t::ceiling, yofs);
@ -2307,11 +2313,12 @@ FUNC(LS_Sector_SetCeilingPanning)
FUNC(LS_Sector_SetFloorPanning)
// Sector_SetFloorPanning (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xofs = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yofs = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetXOffset(sector_t::floor, xofs);
sectors[secnum].SetYOffset(sector_t::floor, yofs);
@ -2322,7 +2329,6 @@ FUNC(LS_Sector_SetFloorPanning)
FUNC(LS_Sector_SetFloorScale)
// Sector_SetFloorScale (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xscale = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yscale = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
@ -2331,7 +2337,9 @@ FUNC(LS_Sector_SetFloorScale)
if (yscale)
yscale = FixedDiv (FRACUNIT, yscale);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (xscale)
sectors[secnum].SetXScale(sector_t::floor, xscale);
@ -2344,7 +2352,6 @@ FUNC(LS_Sector_SetFloorScale)
FUNC(LS_Sector_SetCeilingScale)
// Sector_SetCeilingScale (tag, x-int, x-frac, y-int, y-frac)
{
int secnum = -1;
fixed_t xscale = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
fixed_t yscale = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
@ -2353,7 +2360,9 @@ FUNC(LS_Sector_SetCeilingScale)
if (yscale)
yscale = FixedDiv (FRACUNIT, yscale);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (xscale)
sectors[secnum].SetXScale(sector_t::ceiling, xscale);
@ -2366,14 +2375,14 @@ FUNC(LS_Sector_SetCeilingScale)
FUNC(LS_Sector_SetFloorScale2)
// Sector_SetFloorScale2 (tag, x-factor, y-factor)
{
int secnum = -1;
if (arg1)
arg1 = FixedDiv (FRACUNIT, arg1);
if (arg2)
arg2 = FixedDiv (FRACUNIT, arg2);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (arg1)
sectors[secnum].SetXScale(sector_t::floor, arg1);
@ -2386,14 +2395,14 @@ FUNC(LS_Sector_SetFloorScale2)
FUNC(LS_Sector_SetCeilingScale2)
// Sector_SetFloorScale2 (tag, x-factor, y-factor)
{
int secnum = -1;
if (arg1)
arg1 = FixedDiv (FRACUNIT, arg1);
if (arg2)
arg2 = FixedDiv (FRACUNIT, arg2);
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
if (arg1)
sectors[secnum].SetXScale(sector_t::ceiling, arg1);
@ -2406,11 +2415,12 @@ FUNC(LS_Sector_SetCeilingScale2)
FUNC(LS_Sector_SetRotation)
// Sector_SetRotation (tag, floor-angle, ceiling-angle)
{
int secnum = -1;
angle_t ceiling = arg2 * ANGLE_1;
angle_t floor = arg1 * ANGLE_1;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sectors[secnum].SetAngle(sector_t::floor, floor);
sectors[secnum].SetAngle(sector_t::ceiling, ceiling);
@ -2997,10 +3007,11 @@ FUNC(LS_ForceField)
FUNC(LS_ClearForceField)
// ClearForceField (tag)
{
int secnum = -1;
bool rtn = false;
while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
FSectorTagIterator itr(arg0);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
sector_t *sec = &sectors[secnum];
rtn = true;

View File

@ -220,16 +220,8 @@ bool EV_DoPillar (DPillar::EPillar type, line_t *line, int tag,
bool rtn = false;
// check if a manual trigger; if so do just the sector on the backside
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
secnum = (int)(sec-sectors);
goto manual_pillar;
}
secnum = -1;
while (tag && (secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag, line);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];

View File

@ -233,42 +233,33 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height,
fixed_t newheight = 0;
vertex_t *spot;
if (tag != 0)
{
// Activate all <type> plats that are in_stasis
switch (type)
{
case DPlat::platToggle:
rtn = true;
case DPlat::platPerpetualRaise:
P_ActivateInStasis (tag);
break;
default:
break;
}
}
// [RH] If tag is zero, use the sector on the back side
// of the activating line (if any).
if (!tag)
{
if (!line || !(sec = line->backsector))
return false;
secnum = (int)(sec - sectors);
manual = true;
goto manual_plat;
}
// Activate all <type> plats that are in_stasis
switch (type)
{
case DPlat::platToggle:
rtn = true;
case DPlat::platPerpetualRaise:
P_ActivateInStasis (tag);
break;
default:
break;
}
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag, line);
while ((secnum = itr.Next()) >= 0)
{
sec = &sectors[secnum];
manual_plat:
if (sec->PlaneMoving(sector_t::floor))
{
if (!manual)
continue;
else
return false;
continue;
}
// Find lowest & highest floors around sector
@ -406,8 +397,6 @@ manual_plat:
default:
break;
}
if (manual)
return rtn;
}
return rtn;
}

View File

@ -123,7 +123,7 @@ static void P_CopyPlane (int tag, sector_t *dest, bool copyCeil)
int secnum;
size_t planeofs;
secnum = P_FindSectorFromTag (tag, -1);
secnum = P_FindFirstSectorFromTag (tag);
if (secnum == -1)
{
return;

View File

@ -195,15 +195,36 @@ bool CheckIfExitIsGood (AActor *self, level_info_t *info)
// Find the next sector with a specified tag.
// Rewritten by Lee Killough to use chained hashing to improve speed
int P_FindSectorFromTag (int tag, int start)
int FSectorTagIterator::Next()
{
start = start >= 0 ? sectors[start].nexttag :
sectors[(unsigned) tag % (unsigned) numsectors].firsttag;
while (start >= 0 && sectors[start].tag != tag)
int ret;
if (searchtag == INT_MIN)
{
ret = start;
start = -1;
}
else
{
while (start != -1 && sectors[start].tag != searchtag) start = sectors[start].nexttag;
if (start == -1) return -1;
ret = start;
start = sectors[start].nexttag;
return start;
}
return ret;
}
int FSectorTagIterator::NextCompat(bool compat, int start)
{
if (!compat) return Next();
for (int i = start + 1; i < numsectors; i++)
{
if (sectors[i].HasTag(searchtag)) return i;
}
return -1;
}
// killough 4/16/98: Same thing, only for linedefs
int P_FindLineFromID (int id, int start)
@ -266,7 +287,7 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType)
special && // not for lines without a special
line->args[0] == line->id && // Safety check: exclude edited UDMF linedefs or ones that don't map the tag to args[0]
line->args[0] && // only if there's a tag (which is stored in the first arg)
P_FindSectorFromTag (line->args[0], -1) == -1) // only if no sector is tagged to this linedef
P_FindFirstSectorFromTag (line->args[0]) == -1) // only if no sector is tagged to this linedef
{
P_ChangeSwitchTexture (line->sidedef[0], repeat, special);
line->special = 0;
@ -657,9 +678,9 @@ static void DoSectorDamage(AActor *actor, sector_t *sec, int amount, FName type,
void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, int flags)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
int secnum;
while ((secnum = itr.Next()) >= 0)
{
AActor *actor, *next;
sector_t *sec = &sectors[secnum];
@ -884,12 +905,14 @@ DLightTransfer::DLightTransfer (sector_t *srcSec, int target, bool copyFloor)
if (copyFloor)
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING);
}
else
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING);
}
ChangeStatNum (STAT_LIGHTTRANSFER);
@ -912,12 +935,14 @@ void DLightTransfer::DoTransfer (int level, int target, bool floor)
if (floor)
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].SetPlaneLight(sector_t::floor, level);
}
else
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
FSectorTagIterator itr(target);
while ((secnum = itr.Next()) >= 0)
sectors[secnum].SetPlaneLight(sector_t::ceiling, level);
}
}
@ -1173,7 +1198,9 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
reference->flags |= MF_JUSTATTACKED;
anchor->flags |= MF_JUSTATTACKED;
for (int s=-1; (s = P_FindSectorFromTag(sectortag,s)) >= 0;)
int s;
FSectorTagIterator itr(sectortag);
while ((s = itr.Next()) >= 0)
{
SetPortal(&sectors[s], plane, reference, alpha);
}
@ -1193,7 +1220,8 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
}
else
{
for (int s=-1; (s = P_FindSectorFromTag(lines[j].args[0],s)) >= 0;)
FSectorTagIterator itr(lines[j].args[0]);
while ((s = itr.Next()) >= 0)
{
SetPortal(&sectors[s], plane, reference, alpha);
}
@ -1374,38 +1402,41 @@ void P_SpawnSpecials (void)
// killough 3/7/98:
// support for drawn heights coming from different sector
case Transfer_Heights:
sec = lines[i].frontsector;
if (lines[i].args[1] & 2)
{
sec->MoreFlags |= SECF_FAKEFLOORONLY;
sec = lines[i].frontsector;
if (lines[i].args[1] & 2)
{
sec->MoreFlags |= SECF_FAKEFLOORONLY;
}
if (lines[i].args[1] & 4)
{
sec->MoreFlags |= SECF_CLIPFAKEPLANES;
}
if (lines[i].args[1] & 8)
{
sec->MoreFlags |= SECF_UNDERWATER;
}
else if (forcewater)
{
sec->MoreFlags |= SECF_FORCEDUNDERWATER;
}
if (lines[i].args[1] & 16)
{
sec->MoreFlags |= SECF_IGNOREHEIGHTSEC;
}
if (lines[i].args[1] & 32)
{
sec->MoreFlags |= SECF_NOFAKELIGHT;
}
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
{
sectors[s].heightsec = sec;
sec->e->FakeFloor.Sectors.Push(&sectors[s]);
sectors[s].AdjustFloorClip();
}
break;
}
if (lines[i].args[1] & 4)
{
sec->MoreFlags |= SECF_CLIPFAKEPLANES;
}
if (lines[i].args[1] & 8)
{
sec->MoreFlags |= SECF_UNDERWATER;
}
else if (forcewater)
{
sec->MoreFlags |= SECF_FORCEDUNDERWATER;
}
if (lines[i].args[1] & 16)
{
sec->MoreFlags |= SECF_IGNOREHEIGHTSEC;
}
if (lines[i].args[1] & 32)
{
sec->MoreFlags |= SECF_NOFAKELIGHT;
}
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
{
sectors[s].heightsec = sec;
sec->e->FakeFloor.Sectors.Push(&sectors[s]);
sectors[s].AdjustFloorClip();
}
break;
// killough 3/16/98: Add support for setting
// floor lighting independently (e.g. lava)
@ -1458,9 +1489,10 @@ void P_SpawnSpecials (void)
{
case Init_Gravity:
{
float grav = ((float)P_AproxDistance (lines[i].dx, lines[i].dy)) / (FRACUNIT * 100.0f);
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
sectors[s].gravity = grav;
float grav = ((float)P_AproxDistance (lines[i].dx, lines[i].dy)) / (FRACUNIT * 100.0f);
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
sectors[s].gravity = grav;
}
break;
@ -1470,7 +1502,8 @@ void P_SpawnSpecials (void)
case Init_Damage:
{
int damage = P_AproxDistance (lines[i].dx, lines[i].dy) >> FRACBITS;
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
{
sectors[s].damage = damage;
sectors[s].mod = 0;//MOD_UNKNOWN;
@ -1493,9 +1526,12 @@ void P_SpawnSpecials (void)
// or ceiling texture, to distinguish floor and ceiling sky.
case Init_TransferSky:
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0],s)) >= 0;)
sectors[s].sky = (i+1) | PL_SKYFLAT;
break;
{
FSectorTagIterator itr(lines[i].args[0]);
while ((s = itr.Next()) >= 0)
sectors[s].sky = (i + 1) | PL_SKYFLAT;
break;
}
}
break;
}
@ -1756,7 +1792,7 @@ static void P_SpawnScrollers(void)
if (lines[i].special == Sector_CopyScroller)
{
// don't allow copying the scroller if the sector has the same tag as it would just duplicate it.
if (lines[i].args[0] != lines[i].frontsector->tag)
if (lines[i].frontsector->HasTag(lines[i].args[0]))
{
copyscrollers.Push(i);
}
@ -1832,25 +1868,29 @@ static void P_SpawnScrollers(void)
register int s;
case Scroll_Ceiling:
for (s=-1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0;)
{
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
new DScroller (DScroller::sc_ceiling, -dx, dy, control, s, accel);
new DScroller(DScroller::sc_ceiling, -dx, dy, control, s, accel);
}
for(unsigned j = 0;j < copyscrollers.Size(); j++)
for (unsigned j = 0; j < copyscrollers.Size(); j++)
{
line_t *line = &lines[copyscrollers[j]];
if (line->args[0] == l->args[0] && (line->args[1] & 1))
{
new DScroller (DScroller::sc_ceiling, -dx, dy, control, int(line->frontsector-sectors), accel);
new DScroller(DScroller::sc_ceiling, -dx, dy, control, int(line->frontsector - sectors), accel);
}
}
break;
}
case Scroll_Floor:
if (l->args[2] != 1)
{ // scroll the floor texture
for (s=-1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0;)
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
new DScroller (DScroller::sc_floor, -dx, dy, control, s, accel);
}
@ -1867,7 +1907,8 @@ static void P_SpawnScrollers(void)
if (l->args[2] > 0)
{ // carry objects on the floor
for (s=-1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0;)
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
new DScroller (DScroller::sc_carry, dx, dy, control, s, accel);
}
@ -2041,7 +2082,8 @@ void P_SetSectorFriction (int tag, int amount, bool alterFlag)
// higher friction value actually means 'less friction'.
movefactor = FrictionToMoveFactor(friction);
for (s = -1; (s = P_FindSectorFromTag (tag,s)) >= 0; )
FSectorTagIterator itr(tag);
while ((s = itr.Next()) >= 0)
{
// killough 8/28/98:
//
@ -2153,7 +2195,7 @@ DPusher::DPusher (DPusher::EPusher type, line_t *l, int magnitude, int angle,
int DPusher::CheckForSectorMatch (EPusher type, int tag)
{
if (m_Type == type && sectors[m_Affectee].tag == tag)
if (m_Type == type && sectors[m_Affectee].HasTag(tag))
return m_Affectee;
else
return -1;
@ -2356,20 +2398,27 @@ static void P_SpawnPushers ()
switch (l->special)
{
case Sector_SetWind: // wind
for (s = -1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0 ; )
new DPusher (DPusher::p_wind, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
{
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
new DPusher(DPusher::p_wind, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
l->special = 0;
break;
}
case Sector_SetCurrent: // current
for (s = -1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0 ; )
new DPusher (DPusher::p_current, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
{
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
new DPusher(DPusher::p_current, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s);
l->special = 0;
break;
}
case PointPush_SetForce: // push/pull
if (l->args[0]) { // [RH] Find thing by sector
for (s = -1; (s = P_FindSectorFromTag (l->args[0], s)) >= 0 ; )
FSectorTagIterator itr(l->args[0]);
while ((s = itr.Next()) >= 0)
{
AActor *thing = P_GetPushThing (s);
if (thing) { // No MT_P* means no effect

View File

@ -242,8 +242,45 @@ inline sector_t *getNextSector (line_t *line, const sector_t *sec)
line->frontsector;
}
class FSectorTagIterator
{
protected:
int searchtag;
int start;
public:
FSectorTagIterator(int tag)
{
searchtag = tag;
start = sectors[(unsigned)tag % (unsigned)numsectors].firsttag;
}
// Special constructor for actions that treat tag 0 as 'back of activation line'
FSectorTagIterator(int tag, line_t *line)
{
if (tag == 0)
{
searchtag = INT_MIN;
start = (line == NULL || line->backsector == NULL)? -1 : (int)(line->backsector - sectors);
}
else
{
searchtag = tag;
start = sectors[(unsigned)tag % (unsigned)numsectors].firsttag;
}
}
int Next();
int NextCompat(bool compat, int secnum);
};
inline int P_FindFirstSectorFromTag(int tag)
{
FSectorTagIterator it(tag);
return it.Next();
}
int P_FindSectorFromTag (int tag, int start);
int P_FindLineFromID (int id, int start);

View File

@ -300,9 +300,10 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
if (tag != 0)
{
int secnum = -1;
int secnum;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
while ((secnum = itr.Next()) >= 0)
{
// Scanning the snext links of things in the sector will not work, because
// TeleportDests have MF_NOSECTOR set. So you have to search *everything*.
@ -726,7 +727,8 @@ bool EV_TeleportSector (int tag, int source_tid, int dest_tid, bool fog, int gro
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
FSectorTagIterator itr(tag);
while ((secnum = itr.Next()) >= 0)
{
msecnode_t *node;
const sector_t * const sec = &sectors[secnum];