Merge branch 'udmf-multitag' into 'next'

UDMF: Multitag support

See merge request STJr/SRB2!1097
This commit is contained in:
James R 2020-11-14 19:18:14 -05:00
commit 50e15840fb
26 changed files with 1004 additions and 501 deletions

View File

@ -169,6 +169,7 @@ set(SRB2_CORE_GAME_SOURCES
p_telept.c
p_tick.c
p_user.c
taglist.c
p_local.h
p_maputl.h
@ -180,6 +181,7 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h
p_spec.h
p_tick.h
taglist.h
)
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))

View File

@ -522,6 +522,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_picformats.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
$(OBJDIR)/taglist.o \
$(OBJDIR)/v_video.o \
$(OBJDIR)/s_sound.o \
$(OBJDIR)/sounds.o \

View File

@ -23,6 +23,7 @@
// Some global defines, that configure the game.
#include "doomdef.h"
#include "taglist.h"
#include "m_fixed.h" // See the mapthing_t scale.
//
@ -208,11 +209,10 @@ typedef struct
UINT16 options;
INT16 z;
UINT8 extrainfo;
taglist_t tags;
fixed_t scale;
INT16 tag;
INT32 args[NUMMAPTHINGARGS];
char *stringargs[NUMMAPTHINGSTRINGARGS];
struct mobj_s *mobj;
} mapthing_t;

View File

@ -1608,7 +1608,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
//Hurdler: 3d-floors test
if (gl_frontsector && gl_backsector && gl_frontsector->tag != gl_backsector->tag && (gl_backsector->ffloors || gl_frontsector->ffloors))
if (gl_frontsector && gl_backsector && !Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags) && (gl_backsector->ffloors || gl_frontsector->ffloors))
{
ffloor_t * rover;
fixed_t highcut = 0, lowcut = 0;
@ -1625,6 +1625,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
{
for (rover = gl_backsector->ffloors; rover; rover = rover->next)
{
boolean bothsides = false;
// Skip if it exists on both sectors.
ffloor_t * r2;
for (r2 = gl_frontsector->ffloors; r2; r2 = r2->next)
if (rover->master == r2->master)
{
bothsides = true;
break;
}
if (bothsides) continue;
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
continue;
if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES)
@ -1759,6 +1771,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
{
for (rover = gl_frontsector->ffloors; rover; rover = rover->next)
{
boolean bothsides = false;
// Skip if it exists on both sectors.
ffloor_t * r2;
for (r2 = gl_backsector->ffloors; r2; r2 = r2->next)
if (rover->master == r2->master)
{
bothsides = true;
break;
}
if (bothsides) continue;
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
continue;
if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES))
@ -2384,7 +2408,7 @@ static void HWR_AddLine(seg_t * line)
if (!line->polyseg &&
!line->sidedef->midtexture
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors)
|| (gl_frontsector->tag == gl_backsector->tag)))
|| Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags)))
return; // line is empty, don't even bother
// treat like wide open window instead
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
@ -2423,7 +2447,7 @@ static void HWR_AddLine(seg_t * line)
if (!line->polyseg &&
!line->sidedef->midtexture
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors)
|| (gl_frontsector->tag == gl_backsector->tag)))
|| Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags)))
return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead

View File

@ -32,6 +32,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "taglist.h" // P_FindSpecialLineFromTag
#include "lua_hook.h" // hook_cmd_running errors
#define NOHUD if (hud_running)\

View File

@ -99,8 +99,6 @@ enum line_e {
line_slopetype,
line_frontsector,
line_backsector,
line_firsttag,
line_nexttag,
line_polyobj,
line_text,
line_callcount
@ -125,8 +123,6 @@ static const char *const line_opt[] = {
"slopetype",
"frontsector",
"backsector",
"firsttag",
"nexttag",
"polyobj",
"text",
"callcount",
@ -583,7 +579,7 @@ static int sector_get(lua_State *L)
lua_pushinteger(L, sector->special);
return 1;
case sector_tag:
lua_pushinteger(L, sector->tag);
lua_pushinteger(L, Tag_FGet(&sector->tags));
return 1;
case sector_thinglist: // thinglist
lua_pushcfunction(L, lib_iterateSectorThinglist);
@ -684,7 +680,7 @@ static int sector_set(lua_State *L)
sector->special = (INT16)luaL_checkinteger(L, 3);
break;
case sector_tag:
P_ChangeSectorTag((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
Tag_SectorFSet((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
break;
}
return 0;
@ -823,7 +819,7 @@ static int line_get(lua_State *L)
lua_pushinteger(L, line->special);
return 1;
case line_tag:
lua_pushinteger(L, line->tag);
lua_pushinteger(L, Tag_FGet(&line->tags));
return 1;
case line_args:
LUA_PushUserdata(L, line->args, META_LINEARGS);
@ -871,12 +867,6 @@ static int line_get(lua_State *L)
case line_backsector:
LUA_PushUserdata(L, line->backsector, META_SECTOR);
return 1;
case line_firsttag:
lua_pushinteger(L, line->firsttag);
return 1;
case line_nexttag:
lua_pushinteger(L, line->nexttag);
return 1;
case line_polyobj:
LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
return 1;

View File

@ -848,7 +848,7 @@ static int mapthing_get(lua_State *L)
else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo;
else if(fastcmp(field,"tag"))
number = mt->tag;
number = Tag_FGet(&mt->tags);
else if(fastcmp(field,"args"))
{
LUA_PushUserdata(L, mt->args, META_THINGARGS);
@ -910,7 +910,7 @@ static int mapthing_set(lua_State *L)
mt->extrainfo = (UINT8)extrainfo;
}
else if (fastcmp(field,"tag"))
mt->tag = (INT16)luaL_checkinteger(L, 3);
Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else

View File

@ -1108,7 +1108,6 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->scale = player->mo->scale;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0;

View File

@ -394,8 +394,10 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
INT32 secnum = -1;
sector_t *sec;
ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -593,7 +595,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
}
ceiling->tag = sec->tag;
ceiling->tag = tag;
ceiling->type = type;
firstone = 0;
}
@ -614,8 +616,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
INT32 secnum = -1;
sector_t *sec;
ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -670,7 +674,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
break;
}
ceiling->tag = sec->tag;
ceiling->tag = tag;
ceiling->type = type;
}
return rtn;

View File

@ -3925,11 +3925,12 @@ void A_BossDeath(mobj_t *mo)
else
{
// Bring the egg trap up to the surface
junk.tag = LE_CAPSULE0;
// Incredibly shitty code ahead
Tag_FSet(&junk.tags, LE_CAPSULE0);
EV_DoElevator(&junk, elevateHighest, false);
junk.tag = LE_CAPSULE1;
Tag_FSet(&junk.tags, LE_CAPSULE1);
EV_DoElevator(&junk, elevateUp, false);
junk.tag = LE_CAPSULE2;
Tag_FSet(&junk.tags, LE_CAPSULE2);
EV_DoElevator(&junk, elevateHighest, false);
if (mapheaderinfo[gamemap-1]->muspostbossname[0] &&
@ -4052,7 +4053,7 @@ bossjustdie:
}
case MT_KOOPA:
{
junk.tag = LE_KOOPA;
Tag_FSet(&junk.tags, LE_KOOPA);
EV_DoCeiling(&junk, raiseToHighest);
return;
}
@ -6157,7 +6158,7 @@ void A_RockSpawn(mobj_t *actor)
{
mobj_t *mo;
mobjtype_t type;
INT32 i = P_FindSpecialLineFromTag(12, (INT16)actor->threshold, -1);
INT32 i = Tag_FindLineSpecial(12, (INT16)actor->threshold);
line_t *line;
fixed_t dist;
fixed_t randomoomph;

View File

@ -632,8 +632,10 @@ void T_BounceCheese(bouncecheese_t *bouncer)
fixed_t waterheight;
fixed_t floorheight;
sector_t *actionsector;
INT32 i;
boolean remove;
INT32 i;
mtag_t tag = Tag_FGet(&bouncer->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT
|| bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself!
@ -648,7 +650,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
}
// You can use multiple target sectors, but at your own risk!!!
for (i = -1; (i = P_FindSectorFromTag(bouncer->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
actionsector = &sectors[i];
actionsector->moved = true;
@ -772,6 +774,8 @@ void T_StartCrumble(crumble_t *crumble)
ffloor_t *rover;
sector_t *sector;
INT32 i;
mtag_t tag = Tag_FGet(&crumble->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
// Once done, the no-return thinker just sits there,
// constantly 'returning'... kind of an oxymoron, isn't it?
@ -800,7 +804,7 @@ void T_StartCrumble(crumble_t *crumble)
}
else if (++crumble->timer == 0) // Reposition back to original spot
{
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
@ -836,7 +840,7 @@ void T_StartCrumble(crumble_t *crumble)
// Flash to indicate that the platform is about to return.
if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0))
{
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
@ -928,7 +932,7 @@ void T_StartCrumble(crumble_t *crumble)
P_RemoveThinker(&crumble->thinker);
}
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
sector->moved = true;
@ -944,6 +948,7 @@ void T_StartCrumble(crumble_t *crumble)
void T_MarioBlock(mariothink_t *block)
{
INT32 i;
TAG_ITER_DECLARECOUNTER(0);
T_MovePlane
(
@ -978,8 +983,7 @@ void T_MarioBlock(mariothink_t *block)
block->sector->ceilspeed = 0;
block->direction = 0;
}
for (i = -1; (i = P_FindSectorFromTag(block->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, (INT16)block->tag, i)
P_RecalcPrecipInSector(&sectors[i]);
}
@ -992,8 +996,7 @@ void T_FloatSector(floatthink_t *floater)
// Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(floater->tag, -1);
if (secnum <= 0)
if ((secnum = Tag_Iterate_Sectors((INT16)floater->tag, 0)) < 0)
return;
actionsector = &sectors[secnum];
@ -1131,10 +1134,8 @@ void T_ThwompSector(thwomp_t *thwomp)
// Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(thwomp->tag, -1);
if (secnum <= 0)
return; // Bad bad bad!
if ((secnum = Tag_Iterate_Sectors((INT16)thwomp->tag, 0)) < 0)
return;
actionsector = &sectors[secnum];
@ -1293,8 +1294,10 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
sector_t *sec = NULL;
INT32 secnum = -1;
boolean FOFsector = false;
mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(nobaddies->sourceline->tag, secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -1304,13 +1307,15 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
for (i = 0; i < sec->linecount; i++)
{
INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue;
FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
TAG_ITER_SECTORS(1, tag2, targetsecnum)
{
if (T_SectorHasEnemies(&sectors[targetsecnum]))
return;
@ -1321,7 +1326,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
return;
}
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag);
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", tag);
// No enemies found, run the linedef exec and terminate this thinker
P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL);
@ -1396,6 +1401,8 @@ void T_EachTimeThinker(eachtime_t *eachtime)
boolean floortouch = false;
fixed_t bottomheight, topheight;
ffloor_t *rover;
mtag_t tag = Tag_FGet(&eachtime->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
for (i = 0; i < MAXPLAYERS; i++)
{
@ -1405,7 +1412,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
eachtime->playersOnArea[i] = false;
}
while ((secnum = P_FindSectorFromTag(eachtime->sourceline->tag, secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -1422,13 +1429,15 @@ void T_EachTimeThinker(eachtime_t *eachtime)
for (i = 0; i < sec->linecount; i++)
{
INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue;
FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
TAG_ITER_SECTORS(1, tag2, targetsecnum)
{
targetsec = &sectors[targetsecnum];
@ -1530,7 +1539,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i)))
continue;
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag);
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag);
// 03/08/14 -Monster Iestyn
// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever!
@ -1562,11 +1571,13 @@ void T_RaiseSector(raise_t *raise)
fixed_t distToNearestEndpoint;
INT32 direction;
result_e res = 0;
mtag_t tag = raise->tag;
TAG_ITER_DECLARECOUNTER(0);
if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata)
return;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
sector = &sectors[i];
@ -1693,7 +1704,7 @@ void T_RaiseSector(raise_t *raise)
raise->sector->ceilspeed = 42;
raise->sector->floorspeed = speed*direction;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
P_RecalcPrecipInSector(&sectors[i]);
}
@ -1810,8 +1821,10 @@ void EV_DoFloor(line_t *line, floor_e floortype)
INT32 secnum = -1;
sector_t *sec;
floormove_t *dofloor;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -2025,9 +2038,11 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
INT32 secnum = -1;
sector_t *sec;
elevator_t *elevator;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
// act on all sectors with the same tag as the triggering linedef
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
TAG_ITER_SECTORS(0, tag, secnum)
{
sec = &sectors[secnum];
@ -2148,6 +2163,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
INT16 flags;
sector_t *controlsec = rover->master->frontsector;
mtag_t tag = Tag_FGet(&controlsec->tags);
if (sec == NULL)
{
@ -2176,9 +2192,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
lifetime = 3*TICRATE;
flags = 0;
if (controlsec->tag != 0)
if (tag != 0)
{
INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1);
INT32 tagline = Tag_FindLineSpecial(14, tag);
if (tagline != -1)
{
if (sides[lines[tagline].sidenum[0]].toptexture)
@ -2322,6 +2338,8 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble_t *crumble;
sector_t *foundsec;
INT32 i;
mtag_t tag = Tag_FGet(&rover->master->tags);
TAG_ITER_DECLARECOUNTER(0);
// If floor is already activated, skip it
if (sec->floordata)
@ -2364,7 +2382,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
foundsec = &sectors[i];
@ -2413,7 +2431,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
block->direction = 1;
block->floorstartheight = block->sector->floorheight;
block->ceilingstartheight = block->sector->ceilingheight;
block->tag = (INT16)sector->tag;
block->tag = (INT16)Tag_FGet(&sector->tags);
if (itsamonitor)
{

View File

@ -1388,7 +1388,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bot)
return;
junk.tag = LE_AXE;
Tag_FSet(&junk.tags, LE_AXE);
EV_DoElevator(&junk, bridgeFall, false);
// scan the remaining thinkers to find koopa

View File

@ -374,8 +374,10 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force)
{
INT32 i;
TAG_ITER_DECLARECOUNTER(0);
// search all sectors for ones with tag
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;)
TAG_ITER_SECTORS(0, tag, i)
{
if (!force && ticbased // always let speed fader execute
&& sectors[i].lightingdata

View File

@ -3536,16 +3536,19 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
{
sector_t *sector;
fixed_t halfheight = thiscam->z + (thiscam->height >> 1);
size_t i;
// see if we are in water
sector = thiscam->subsector->sector;
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
return true;
for (i = 0; i < sector->tags.count; i++)
if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
return true;
if (sector->ffloors)
{
ffloor_t *rover;
size_t j;
for (rover = sector->ffloors; rover; rover = rover->next)
{
@ -3557,7 +3560,8 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
for (j = 0; j < rover->master->frontsector->tags.count; j++)
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
return true;
}
}
@ -4626,16 +4630,18 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta)
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum;
sector_t *sector;
for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag)
boolean gotcage = false;
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_SECTORS(0, tag, snum)
{
sector = &sectors[snum];
if (sector->tag != tag)
continue;
sector->floorheight += delta;
sector->ceilingheight += delta;
P_CheckSector(sector, true);
gotcage = true;
}
return sectors[tag%numsectors].firsttag != -1;
return gotcage;
}
// Move Boss4's arms to angle
@ -4707,26 +4713,16 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
static void P_Boss4DestroyCage(mobj_t *mobj)
{
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum, next;
INT32 snum;
size_t a;
sector_t *sector, *rsec;
ffloor_t *rover;
TAG_ITER_DECLARECOUNTER(0);
// This will be the final iteration of sector tag.
// We'll destroy the tag list as we go.
next = sectors[tag%numsectors].firsttag;
sectors[tag%numsectors].firsttag = -1;
for (snum = next; snum != -1; snum = next)
TAG_ITER_SECTORS(0, tag, snum)
{
sector = &sectors[snum];
next = sector->nexttag;
sector->nexttag = -1;
if (sector->tag != tag)
continue;
sector->tag = 0;
// Destroy the FOFs.
for (a = 0; a < sector->numattached; a++)
{
@ -10046,11 +10042,12 @@ void P_MobjThinker(mobj_t *mobj)
// Sector special (2,8) allows ANY mobj to trigger a linedef exec
if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
{
sector_t *sec2;
sec2 = P_ThingOnSpecial3DFloor(mobj);
sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
{
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
}
if (mobj->scale != mobj->destscale)
@ -10274,14 +10271,19 @@ void P_PushableThinker(mobj_t *mobj)
sec = mobj->subsector->sector;
if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight)
P_LinedefExecute(sec->tag, mobj, sec);
{
mtag_t tag = Tag_FGet(&sec->tags);
P_LinedefExecute(tag, mobj, sec);
}
// else if (GETSECSPECIAL(sec->special, 2) == 8)
{
sector_t *sec2;
sec2 = P_ThingOnSpecial3DFloor(mobj);
sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
{
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
}
// it has to be pushable RIGHT NOW for this part to happen
@ -12030,8 +12032,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag
// P_FindSpecialLineFromTag works here now =D
line = P_FindSpecialLineFromTag(9, mthing->angle, -1);
line = Tag_FindLineSpecial(9, mthing->angle);
if (line == -1)
{
@ -12341,7 +12342,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag
line = P_FindSpecialLineFromTag(15, mthing->angle, -1);
line = Tag_FindLineSpecial(15, mthing->angle);
if (line == -1)
{
@ -12580,17 +12581,20 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
break;
}
case MT_SKYBOX:
if (mthing->tag < 0 || mthing->tag > 15)
{
mtag_t tag = Tag_FGet(&mthing->tags);
if (tag < 0 || tag > 15)
{
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", mthing->tag, sizeu1((size_t)(mthing - mapthings)));
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", tag, sizeu1((size_t)(mthing - mapthings)));
break;
}
if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->tag] = mobj;
skyboxcenterpnts[tag] = mobj;
else
skyboxviewpnts[mthing->tag] = mobj;
skyboxviewpnts[tag] = mobj;
break;
}
case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA)
{

View File

@ -556,10 +556,11 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
polyobj_t *po;
vertex_t dist, sspot;
size_t i;
mtag_t tag = Tag_FGet(&anchor->tags);
if (!(po = Polyobj_GetForNum(anchor->tag)))
if (!(po = Polyobj_GetForNum(tag)))
{
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->tag);
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", tag);
return;
}
@ -1342,7 +1343,7 @@ void Polyobj_InitLevel(void)
{
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tag);
Polyobj_spawnPolyObj(i, qitem->mo, Tag_FGet(&qitem->mo->spawnpoint->tags));
}
// move polyobjects to spawn points
@ -2444,10 +2445,11 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
polymove_t *th;
size_t i;
INT32 start;
mtag_t tag = pfdata->polyObjNum;
if (!(po = Polyobj_GetForNum(pfdata->polyObjNum)))
if (!(po = Polyobj_GetForNum(tag)))
{
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum);
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", tag);
return false;
}
@ -2470,7 +2472,7 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
po->thinker = &th->thinker;
// set fields
th->polyObjNum = pfdata->polyObjNum;
th->polyObjNum = tag;
th->distance = 0;
th->speed = pfdata->speed;
th->angle = pfdata->angle;

View File

@ -923,7 +923,7 @@ static void UnArchiveFFloors(const sector_t *ss)
static void ArchiveSectors(void)
{
size_t i;
size_t i, j;
const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3;
@ -961,10 +961,8 @@ static void ArchiveSectors(void)
if (ss->ceilingpic_angle != spawnss->ceilingpic_angle)
diff2 |= SD_CEILANG;
if (ss->tag != spawnss->tag)
if (!Tag_Compare(&ss->tags, &spawnss->tags))
diff2 |= SD_TAG;
if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag)
diff3 |= SD_TAGLIST;
if (ss->extra_colormap != spawnss->extra_colormap)
diff3 |= SD_COLORMAP;
@ -1012,12 +1010,11 @@ static void ArchiveSectors(void)
WRITEANGLE(save_p, ss->floorpic_angle);
if (diff2 & SD_CEILANG)
WRITEANGLE(save_p, ss->ceilingpic_angle);
if (diff2 & SD_TAG) // save only the tag
WRITEINT16(save_p, ss->tag);
if (diff3 & SD_TAGLIST) // save both firsttag and nexttag
{ // either of these could be changed even if tag isn't
WRITEINT32(save_p, ss->firsttag);
WRITEINT32(save_p, ss->nexttag);
if (diff2 & SD_TAG)
{
WRITEUINT32(save_p, ss->tags.count);
for (j = 0; j < ss->tags.count; j++)
WRITEINT16(save_p, ss->tags.tags[j]);
}
if (diff3 & SD_COLORMAP)
@ -1035,7 +1032,7 @@ static void ArchiveSectors(void)
static void UnArchiveSectors(void)
{
UINT16 i;
UINT16 i, j;
UINT8 diff, diff2, diff3;
for (;;)
{
@ -1089,13 +1086,29 @@ static void UnArchiveSectors(void)
if (diff2 & SD_CEILANG)
sectors[i].ceilingpic_angle = READANGLE(save_p);
if (diff2 & SD_TAG)
sectors[i].tag = READINT16(save_p); // DON'T use P_ChangeSectorTag
if (diff3 & SD_TAGLIST)
{
sectors[i].firsttag = READINT32(save_p);
sectors[i].nexttag = READINT32(save_p);
size_t ncount = READUINT32(save_p);
// Remove entries from global lists.
for (j = 0; j < sectors[i].tags.count; j++)
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
// Reallocate if size differs.
if (ncount != sectors[i].tags.count)
{
sectors[i].tags.count = ncount;
sectors[i].tags.tags = Z_Realloc(sectors[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL);
}
for (j = 0; j < ncount; j++)
sectors[i].tags.tags[j] = READINT16(save_p);
// Add new entries.
for (j = 0; j < sectors[i].tags.count; j++)
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
}
if (diff3 & SD_COLORMAP)
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
if (diff3 & SD_CRUMBLESTATE)

View File

@ -82,6 +82,8 @@
#include "fastcmp.h" // textmap parsing
#include "taglist.h"
//
// Map MD5, calculated on level load.
// Sent to clients in PT_SERVERINFO.
@ -963,8 +965,6 @@ static void P_LoadVertices(UINT8 *data)
static void P_InitializeSector(sector_t *ss)
{
ss->nexttag = ss->firsttag = -1;
memset(&ss->soundorg, 0, sizeof(ss->soundorg));
ss->validcount = 0;
@ -1035,7 +1035,7 @@ static void P_LoadSectors(UINT8 *data)
ss->lightlevel = SHORT(ms->lightlevel);
ss->special = SHORT(ms->special);
ss->tag = SHORT(ms->tag);
Tag_FSet(&ss->tags, SHORT(ms->tag));
ss->floor_xoffs = ss->floor_yoffs = 0;
ss->ceiling_xoffs = ss->ceiling_yoffs = 0;
@ -1077,7 +1077,6 @@ static void P_InitializeLinedef(line_t *ld)
#ifdef WALLSPLATS
ld->splats = NULL;
#endif
ld->firsttag = ld->nexttag = -1;
ld->polyobj = NULL;
ld->text = NULL;
@ -1149,7 +1148,7 @@ static void P_LoadLinedefs(UINT8 *data)
{
ld->flags = SHORT(mld->flags);
ld->special = SHORT(mld->special);
ld->tag = SHORT(mld->tag);
Tag_FSet(&ld->tags, SHORT(mld->tag));
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT;
@ -1342,7 +1341,7 @@ static void P_LoadSidedefs(UINT8 *data)
|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F'))
sd->toptexture = axtoi(msd->toptexture);
else
I_Error("Custom FOF (tag %d) needs a value in the linedef's back side upper texture field.", sd->line->tag);
I_Error("Custom FOF (line id %s) needs a value in the linedef's back side upper texture field.", sizeu1(sd->line - lines));
sd->midtexture = R_TextureNumForName(msd->midtexture);
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
@ -1382,8 +1381,8 @@ static void P_LoadThings(UINT8 *data)
mt->type = READUINT16(data);
mt->options = READUINT16(data);
mt->extrainfo = (UINT8)(mt->type >> 12);
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0;
@ -1519,7 +1518,17 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
else if (fastcmp(param, "special"))
sectors[i].special = atol(val);
else if (fastcmp(param, "id"))
sectors[i].tag = atol(val);
Tag_FSet(&sectors[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&sectors[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "xpanningfloor"))
sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "ypanningfloor"))
@ -1597,7 +1606,17 @@ static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val)
static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
{
if (fastcmp(param, "id"))
lines[i].tag = atol(val);
Tag_FSet(&lines[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&lines[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "special"))
lines[i].special = atol(val);
else if (fastcmp(param, "v1"))
@ -1666,8 +1685,18 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
{
if (fastcmp(param, "id"))
mapthings[i].tag = atol(val);
if (fastcmp(param, "x"))
Tag_FSet(&mapthings[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&mapthings[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "x"))
mapthings[i].x = atol(val);
else if (fastcmp(param, "y"))
mapthings[i].y = atol(val);
@ -1824,7 +1853,7 @@ static void P_LoadTextmap(void)
sc->lightlevel = 255;
sc->special = 0;
sc->tag = 0;
Tag_FSet(&sc->tags, 0);
sc->floor_xoffs = sc->floor_yoffs = 0;
sc->ceiling_xoffs = sc->ceiling_yoffs = 0;
@ -1842,6 +1871,7 @@ static void P_LoadTextmap(void)
textmap_colormap.fadeend = 31;
textmap_colormap.flags = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc);
if (textmap_colormap.used)
{
@ -1858,7 +1888,8 @@ static void P_LoadTextmap(void)
ld->v1 = ld->v2 = NULL;
ld->flags = 0;
ld->special = 0;
ld->tag = 0;
Tag_FSet(&ld->tags, 0);
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT;
@ -1906,8 +1937,8 @@ static void P_LoadTextmap(void)
mt->options = 0;
mt->z = 0;
mt->extrainfo = 0;
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL;
@ -2924,30 +2955,6 @@ static void P_LinkMapData(void)
}
}
/** Hashes the sector tags across the sectors and linedefs.
*
* \sa P_FindSectorFromTag, P_ChangeSectorTag
* \author Lee Killough
*/
static inline void P_InitTagLists(void)
{
register size_t i;
for (i = numsectors - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)sectors[i].tag % numsectors;
sectors[i].nexttag = sectors[j].firsttag;
sectors[j].firsttag = (INT32)i;
}
for (i = numlines - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)lines[i].tag % numlines;
lines[i].nexttag = lines[j].firsttag;
lines[j].firsttag = (INT32)i;
}
}
//For maps in binary format, converts setup of specials to UDMF format.
static void P_ConvertBinaryMap(void)
{
@ -2955,14 +2962,28 @@ static void P_ConvertBinaryMap(void)
for (i = 0; i < numlines; i++)
{
mtag_t tag = Tag_FGet(&lines[i].tags);
switch (lines[i].special)
{
case 20: //PolyObject first line
{
INT32 paramline = P_FindSpecialLineFromTag(22, lines[i].tag, -1);
INT32 check = -1;
INT32 paramline = -1;
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_LINES(0, tag, check)
{
if (lines[check].special == 22)
{
paramline = check;
break;
}
}
//PolyObject ID
lines[i].args[0] = lines[i].tag;
lines[i].args[0] = tag;
//Default: Invisible planes
lines[i].args[3] |= TMPF_INVISIBLEPLANES;
@ -3008,7 +3029,7 @@ static void P_ConvertBinaryMap(void)
CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i));
break;
case 447: //Change colormap
lines[i].args[0] = lines[i].tag;
lines[i].args[0] = Tag_FGet(&lines[i].tags);
if (lines[i].flags & ML_EFFECT3)
lines[i].args[2] |= TMCF_RELATIVE;
if (lines[i].flags & ML_EFFECT1)
@ -3024,7 +3045,7 @@ static void P_ConvertBinaryMap(void)
abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS)
: abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS));
lines[i].args[0] = lines[i].tag;
lines[i].args[0] = Tag_FGet(&lines[i].tags);
if (lines[i].flags & ML_EFFECT4)
lines[i].args[2] = speed;
else
@ -3044,10 +3065,10 @@ static void P_ConvertBinaryMap(void)
break;
}
case 456: //Stop fading colormap
lines[i].args[0] = lines[i].tag;
lines[i].args[0] = Tag_FGet(&lines[i].tags);
break;
case 606: //Colormap
lines[i].args[0] = lines[i].tag;
lines[i].args[0] = Tag_FGet(&lines[i].tags);
break;
case 700: //Slope front sector floor
case 701: //Slope front sector ceiling
@ -3088,7 +3109,7 @@ static void P_ConvertBinaryMap(void)
else if (lines[i].special == 715)
lines[i].args[0] = TMSP_BACKCEILING;
lines[i].args[1] = lines[i].tag;
lines[i].args[1] = tag;
if (lines[i].flags & ML_EFFECT6)
{
@ -3120,9 +3141,9 @@ static void P_ConvertBinaryMap(void)
case 721: //Copy front side ceiling slope
case 722: //Copy front side floor and ceiling slope
if (lines[i].special != 721)
lines[i].args[0] = lines[i].tag;
lines[i].args[0] = tag;
if (lines[i].special != 720)
lines[i].args[1] = lines[i].tag;
lines[i].args[1] = tag;
lines[i].special = 720;
break;
case 900: //Translucent wall (10%)
@ -3155,21 +3176,39 @@ static void P_ConvertBinaryMap(void)
switch (mapthings[i].type)
{
case 750:
Tag_Add(&mapthings[i].tags, mapthings[i].angle);
break;
case 760:
case 761:
mapthings[i].tag = mapthings[i].angle;
Tag_FSet(&mapthings[i].tags, mapthings[i].angle);
break;
case 762:
{
INT32 firstline = P_FindSpecialLineFromTag(20, mapthings[i].angle, -1);
INT32 check = -1;
INT32 firstline = -1;
mtag_t tag = mapthings[i].angle;
TAG_ITER_DECLARECOUNTER(0);
Tag_FSet(&mapthings[i].tags, tag);
TAG_ITER_LINES(0, tag, check)
{
if (lines[check].special == 20)
{
firstline = check;
break;
}
}
if (firstline != -1)
lines[firstline].args[3] |= TMPF_CRUSH;
mapthings[i].tag = mapthings[i].angle;
mapthings[i].type = 761;
break;
}
case 780:
mapthings[i].tag = mapthings[i].extrainfo;
Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo);
break;
default:
break;
@ -3243,6 +3282,7 @@ static boolean P_LoadMapFromFile(void)
{
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
size_t i;
udmf = textmap != NULL;
if (!P_LoadMapData(virt))
@ -3252,7 +3292,7 @@ static boolean P_LoadMapFromFile(void)
P_LinkMapData();
P_InitTagLists(); // Create xref tables for tags
Taglist_InitGlobalTables();
if (!udmf)
P_ConvertBinaryMap();
@ -3266,6 +3306,10 @@ static boolean P_LoadMapFromFile(void)
memcpy(spawnlines, lines, numlines * sizeof(*lines));
memcpy(spawnsides, sides, numsides * sizeof(*sides));
for (i = 0; i < numsectors; i++)
if (sectors[i].tags.count)
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
P_MakeMapMD5(virt, &mapmd5);
vres_Free(virt);

View File

@ -139,7 +139,7 @@ void T_DynamicSlopeVert (dynplanethink_t* th)
INT32 l;
for (i = 0; i < 3; i++) {
l = P_FindSpecialLineFromTag(799, th->tags[i], -1);
l = Tag_FindLineSpecial(799, th->tags[i]);
if (l != -1) {
th->vex[i].z = lines[l].frontsector->floorheight;
}
@ -405,9 +405,6 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL);
}
}
if(!line->tag)
return;
}
/// Creates a new slope from three mapthings with the specified IDs
@ -426,11 +423,11 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue;
if (!vertices[0] && mt->tag == tag1)
if (!vertices[0] && Tag_Find(&mt->tags, tag1))
vertices[0] = mt;
else if (!vertices[1] && mt->tag == tag2)
else if (!vertices[1] && Tag_Find(&mt->tags, tag2))
vertices[1] = mt;
else if (!vertices[2] && mt->tag == tag3)
else if (!vertices[2] && Tag_Find(&mt->tags, tag3))
vertices[2] = mt;
}
@ -549,11 +546,11 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling)
{
INT32 i;
pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope;
TAG_ITER_DECLARECOUNTER(0);
if (!tag || *secslope)
return false;
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;)
TAG_ITER_SECTORS(0, tag, i)
{
pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope;
if (srcslope)

File diff suppressed because it is too large Load Diff

View File

@ -55,9 +55,6 @@ fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight);
fixed_t P_FindLowestCeilingSurrounding(sector_t *sec);
fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
INT32 P_FindSectorFromTag(INT16 tag, INT32 start);
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start);
INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_SetupSignExit(player_t *player);
@ -67,7 +64,6 @@ void P_SwitchWeather(INT32 weathernum);
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
void P_RunNightserizeExecutors(mobj_t *actor);
void P_RunDeNightserizeExecutors(mobj_t *actor);
void P_RunNightsLapExecutors(mobj_t *actor);

View File

@ -10579,6 +10579,7 @@ static void P_CalcPostImg(player_t *player)
postimg_t *type;
INT32 *param;
fixed_t pviewheight;
size_t i;
if (player->mo->eflags & MFE_VERTICALFLIP)
pviewheight = player->mo->z + player->mo->height - player->viewheight;
@ -10603,28 +10604,45 @@ static void P_CalcPostImg(player_t *player)
}
// see if we are in heat (no, not THAT kind of heat...)
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
*type = postimg_heat;
else if (sector->ffloors)
for (i = 0; i < sector->tags.count; i++)
{
ffloor_t *rover;
fixed_t topheight;
fixed_t bottomheight;
for (rover = sector->ffloors; rover; rover = rover->next)
if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
{
if (!(rover->flags & FF_EXISTS))
continue;
*type = postimg_heat;
break;
}
else if (sector->ffloors)
{
ffloor_t *rover;
fixed_t topheight;
fixed_t bottomheight;
boolean gotres = false;
topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y);
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
for (rover = sector->ffloors; rover; rover = rover->next)
{
size_t j;
if (pviewheight >= topheight || pviewheight <= bottomheight)
continue;
if (!(rover->flags & FF_EXISTS))
continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
*type = postimg_heat;
topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y);
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
if (pviewheight >= topheight || pviewheight <= bottomheight)
continue;
for (j = 0; j < rover->master->frontsector->tags.count; j++)
{
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
{
*type = postimg_heat;
gotres = true;
break;
}
}
}
if (gotres)
break;
}
}
@ -10723,22 +10741,21 @@ static sector_t *P_GetMinecartSector(fixed_t x, fixed_t y, fixed_t z, fixed_t *n
static INT32 P_GetMinecartSpecialLine(sector_t *sec)
{
INT32 line = -1;
size_t i;
if (!sec)
return line;
if (sec->tag != 0)
line = P_FindSpecialLineFromTag(16, sec->tag, -1);
for (i = 0; i < sec->tags.count; i++)
if (sec->tags.tags[i] != 0)
line = Tag_FindLineSpecial(16, sec->tags.tags[i]);
// Also try for lines facing the sector itself, with tag 0.
for (i = 0; i < sec->linecount; i++)
{
UINT32 i;
for (i = 0; i < sec->linecount; i++)
{
line_t *li = sec->lines[i];
if (li->tag == 0 && li->special == 16 && li->frontsector == sec)
line = li - lines;
}
line_t *li = sec->lines[i];
if (Tag_Find(&li->tags, 0) && li->special == 16 && li->frontsector == sec)
line = li - lines;
}
return line;
@ -12297,12 +12314,14 @@ void P_PlayerThink(player_t *player)
sector_t *controlsec;
for (j=0; j<numsectors; j++)
{
mtag_t sectag = Tag_FGet(&sectors[j].tags);
controlsec = NULL;
// Does this sector have a water linedef?
for (i=0; i<numlines;i++)
{
mtag_t linetag = Tag_FGet(&lines[i].tags);
if ((lines[i].special == 121 || lines[i].special == 123)
&& lines[i].tag == sectors[j].tag)
&& linetag == sectag)
{
controlsec = lines[i].frontsector;
break;
@ -12311,15 +12330,16 @@ void P_PlayerThink(player_t *player)
if (i < numlines && controlsec)
{
controlsectag = Tag_FGet(&controlsec->tags);
// Does this sector have a colormap?
for (i=0; i<numlines;i++)
{
if (lines[i].special == 606 && lines[i].tag == controlsec->tag)
if (lines[i].special == 606 && linetag == controlsectag)
break;
}
if (i == numlines)
CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectors[j].tag);
CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectag);
}
}

View File

@ -21,6 +21,7 @@
#include "p_local.h" // camera
#include "p_slopes.h"
#include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h"
seg_t *curline;
side_t *sidedef;
@ -374,7 +375,7 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
// Consider colormaps
&& back->extra_colormap == front->extra_colormap
&& ((!front->ffloors && !back->ffloors)
|| front->tag == back->tag));
|| Tag_Compare(&front->tags, &back->tags)));
}
//
@ -448,21 +449,25 @@ static void R_AddLine(seg_t *line)
// Portal line
if (line->linedef->special == 40 && line->side == 0)
{
// Render portal if recursiveness limit hasn't been reached.
// Otherwise, render the wall normally.
if (portalrender < cv_maxportals.value)
{
// Find the other side!
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1);
if (line->linedef == &lines[line2])
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2);
if (line2 >= 0) // found it!
size_t p;
mtag_t tag = Tag_FGet(&line->linedef->tags);
INT32 li1 = line->linedef-lines;
INT32 li2;
for (p = 0; (li2 = Tag_Iterate_Lines(tag, p)) >= 0; p++)
{
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
//return; // Don't fill in that space now!
// Skip invalid lines.
if ((tag != Tag_FGet(&lines[li2].tags)) || (lines[li1].special != lines[li2].special) || (li1 == li2))
continue;
Portal_Add2Lines(li1, li2, x1, x2);
goto clipsolid;
}
}
// Recursed TOO FAR (viewing a portal within a portal)
// So uhhh, render it as a normal wall instead or something ???
}
// Single sided line?
@ -483,7 +488,7 @@ static void R_AddLine(seg_t *line)
if (!line->polyseg &&
!line->sidedef->midtexture
&& ((!frontsector->ffloors && !backsector->ffloors)
|| (frontsector->tag == backsector->tag)))
|| Tag_Compare(&frontsector->tags, &backsector->tags)))
return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead

View File

@ -28,6 +28,8 @@
#include "m_aatree.h"
#endif
#include "taglist.h"
//
// ClipWallSegment
// Clips the given range of columns
@ -281,8 +283,7 @@ typedef struct sector_s
INT32 ceilingpic;
INT16 lightlevel;
INT16 special;
UINT16 tag;
INT32 nexttag, firsttag; // for fast tag searches
taglist_t tags;
// origin for any sounds played by the sector
// also considered the center for e.g. Mario blocks
@ -389,7 +390,7 @@ typedef struct line_s
// Animation related.
INT16 flags;
INT16 special;
INT16 tag;
taglist_t tags;
INT32 args[NUMLINEARGS];
char *stringargs[NUMLINESTRINGARGS];
@ -412,7 +413,6 @@ typedef struct line_s
#if 1//#ifdef WALLSPLATS
void *splats; // wallsplat_t list
#endif
INT32 firsttag, nexttag; // improves searches for tags.
polyobj_t *polyobj; // Belongs to a polyobject?
char *text; // a concatenation of all front and back texture names, for linedef specials that require a string.

View File

@ -25,6 +25,7 @@
#include "p_local.h" // Camera...
#include "p_slopes.h"
#include "console.h" // con_clipviewtop
#include "taglist.h"
// OPTIMIZE: closed two sided lines as single sided
@ -2067,7 +2068,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->floorlightsec != frontsector->floorlightsec
//SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap
|| (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
{
markfloor = true;
}
@ -2098,7 +2099,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->ceilinglightsec != frontsector->ceilinglightsec
//SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap
|| (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
{
markceiling = true;
}
@ -2188,7 +2189,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
rw_bottomtexturemid += sidedef->rowoffset;
// allocate space for masked texture tables
if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors))
if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors))
{
ffloor_t *rover;
ffloor_t *r2;
@ -2230,6 +2231,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (r2 = frontsector->ffloors; r2; r2 = r2->next)
{
if (r2->master == rover->master) // Skip if same control line.
break;
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue;
@ -2285,6 +2289,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (r2 = backsector->ffloors; r2; r2 = r2->next)
{
if (r2->master == rover->master) // Skip if same control line.
break;
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue;

366
src/taglist.c Normal file
View File

@ -0,0 +1,366 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// Copyright (C) 2020 by Nev3r.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file taglist.c
/// \brief Ingame sector/line/mapthing tagging.
#include "taglist.h"
#include "z_zone.h"
#include "r_data.h"
// Taggroups are used to list elements of the same tag, for iteration.
// Since elements can now have multiple tags, it means an element may appear
// in several taggroups at the same time. These are built on level load.
taggroup_t* tags_sectors[MAXTAGS + 1];
taggroup_t* tags_lines[MAXTAGS + 1];
taggroup_t* tags_mapthings[MAXTAGS + 1];
/// Adds a tag to a given element's taglist.
/// \warning This does not rebuild the global taggroups, which are used for iteration.
void Tag_Add (taglist_t* list, const mtag_t tag)
{
list->tags = Z_Realloc(list->tags, (list->count + 1) * sizeof(list->tags), PU_LEVEL, NULL);
list->tags[list->count++] = tag;
}
/// Sets the first tag entry in a taglist.
/// Replicates the old way of accessing element->tag.
void Tag_FSet (taglist_t* list, const mtag_t tag)
{
if (!list->count)
{
Tag_Add(list, tag);
return;
}
list->tags[0] = tag;
}
/// Gets the first tag entry in a taglist.
/// Replicates the old way of accessing element->tag.
mtag_t Tag_FGet (const taglist_t* list)
{
if (list->count)
return list->tags[0];
return 0;
}
/// Returns true if the given tag exist inside the list.
boolean Tag_Find (const taglist_t* list, const mtag_t tag)
{
size_t i;
for (i = 0; i < list->count; i++)
if (list->tags[i] == tag)
return true;
return false;
}
/// Returns true if at least one tag is shared between two given lists.
boolean Tag_Share (const taglist_t* list1, const taglist_t* list2)
{
size_t i;
for (i = 0; i < list1->count; i++)
if (Tag_Find(list2, list1->tags[i]))
return true;
return false;
}
/// Returns true if both lists are identical.
boolean Tag_Compare (const taglist_t* list1, const taglist_t* list2)
{
size_t i;
if (list1->count != list2->count)
return false;
for (i = 0; i < list1->count; i++)
if (list1->tags[i] != list2->tags[i])
return false;
return true;
}
/// Search for an element inside a global taggroup.
size_t Taggroup_Find (const taggroup_t *group, const size_t id)
{
size_t i;
if (!group)
return -1;
for (i = 0; i < group->count; i++)
if (group->elements[i] == id)
return i;
return -1;
}
/// Add an element to a global taggroup.
void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id)
{
taggroup_t *group;
size_t i; // Insert position.
if (tag == MTAG_GLOBAL)
return;
group = garray[(UINT16)tag];
// Don't add duplicate entries.
if (Taggroup_Find(group, id) != (size_t)-1)
return;
// Create group if empty.
if (!group)
{
i = 0;
group = garray[(UINT16)tag] = Z_Calloc(sizeof(taggroup_t), PU_LEVEL, NULL);
}
else
{
// Keep the group element ids in an ascending order.
// Find the location to insert the element to.
for (i = 0; i < group->count; i++)
if (group->elements[i] > id)
break;
group->elements = Z_Realloc(group->elements, (group->count + 1) * sizeof(size_t), PU_LEVEL, NULL);
// Offset existing elements to make room for the new one.
if (i < group->count)
memmove(&group->elements[i + 1], &group->elements[i], group->count - i);
}
group->count++;
group->elements = Z_Realloc(group->elements, group->count * sizeof(size_t), PU_LEVEL, NULL);
group->elements[i] = id;
}
/// Remove an element from a global taggroup.
void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id)
{
taggroup_t *group;
size_t rempos;
size_t newcount;
if (tag == MTAG_GLOBAL)
return;
group = garray[(UINT16)tag];
if ((rempos = Taggroup_Find(group, id)) == (size_t)-1)
return;
// Strip away taggroup if no elements left.
if (!(newcount = --group->count))
{
Z_Free(group->elements);
Z_Free(group);
garray[(UINT16)tag] = NULL;
}
else
{
size_t *newelements = Z_Malloc(newcount * sizeof(size_t), PU_LEVEL, NULL);
size_t i;
// Copy the previous entries save for the one to remove.
for (i = 0; i < rempos; i++)
newelements[i] = group->elements[i];
for (i = rempos + 1; i < group->count; i++)
newelements[i - 1] = group->elements[i];
Z_Free(group->elements);
group->elements = newelements;
group->count = newcount;
}
}
// Initialization.
static void Taglist_AddToSectors (const mtag_t tag, const size_t itemid)
{
Taggroup_Add(tags_sectors, tag, itemid);
}
static void Taglist_AddToLines (const mtag_t tag, const size_t itemid)
{
Taggroup_Add(tags_lines, tag, itemid);
}
static void Taglist_AddToMapthings (const mtag_t tag, const size_t itemid)
{
Taggroup_Add(tags_mapthings, tag, itemid);
}
/// After all taglists have been built for each element (sectors, lines, things),
/// the global taggroups, made for iteration, are built here.
void Taglist_InitGlobalTables(void)
{
size_t i, j;
for (i = 0; i < MAXTAGS; i++)
{
tags_sectors[i] = NULL;
tags_lines[i] = NULL;
tags_mapthings[i] = NULL;
}
for (i = 0; i < numsectors; i++)
{
for (j = 0; j < sectors[i].tags.count; j++)
Taglist_AddToSectors(sectors[i].tags.tags[j], i);
}
for (i = 0; i < numlines; i++)
{
for (j = 0; j < lines[i].tags.count; j++)
Taglist_AddToLines(lines[i].tags.tags[j], i);
}
for (i = 0; i < nummapthings; i++)
{
for (j = 0; j < mapthings[i].tags.count; j++)
Taglist_AddToMapthings(mapthings[i].tags.tags[j], i);
}
}
// Iteration, ingame search.
INT32 Tag_Iterate_Sectors (const mtag_t tag, const size_t p)
{
if (tag == MTAG_GLOBAL)
{
if (p < numsectors)
return p;
return -1;
}
if (tags_sectors[(UINT16)tag])
{
if (p < tags_sectors[(UINT16)tag]->count)
return tags_sectors[(UINT16)tag]->elements[p];
return -1;
}
return -1;
}
INT32 Tag_Iterate_Lines (const mtag_t tag, const size_t p)
{
if (tag == MTAG_GLOBAL)
{
if (p < numlines)
return p;
return -1;
}
if (tags_lines[(UINT16)tag])
{
if (p < tags_lines[(UINT16)tag]->count)
return tags_lines[(UINT16)tag]->elements[p];
return -1;
}
return -1;
}
INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p)
{
if (tag == MTAG_GLOBAL)
{
if (p < nummapthings)
return p;
return -1;
}
if (tags_mapthings[(UINT16)tag])
{
if (p < tags_mapthings[(UINT16)tag]->count)
return tags_mapthings[(UINT16)tag]->elements[p];
return -1;
}
return -1;
}
INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag)
{
size_t i;
if (tag == MTAG_GLOBAL)
{
for (i = 0; i < numlines; i++)
if (lines[i].special == special)
return i;
}
else if (tags_lines[(UINT16)tag])
{
taggroup_t *tagged = tags_lines[(UINT16)tag];
for (i = 0; i < tagged->count; i++)
if (lines[tagged->elements[i]].special == special)
return tagged->elements[i];
}
return -1;
}
/// Backwards compatibility iteration function for Lua scripts.
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start)
{
if (tag == -1)
{
start++;
if (start >= (INT32)numlines)
return -1;
while (start < (INT32)numlines && lines[start].special != special)
start++;
return start;
}
else
{
size_t p = 0;
INT32 id;
// For backwards compatibility's sake, simulate the old linked taglist behavior:
// Iterate through the taglist and find the "start" line's position in the list,
// And start checking with the next one (if it exists).
if (start != -1)
{
for (; (id = Tag_Iterate_Lines(tag, p)) >= 0; p++)
if (id == start)
{
p++;
break;
}
}
for (; (id = Tag_Iterate_Lines(tag, p)) >= 0; p++)
if (lines[id].special == special)
return id;
return -1;
}
}
// Ingame list manipulation.
/// Changes the first tag for a given sector, and updates the global taggroups.
void Tag_SectorFSet (const size_t id, const mtag_t tag)
{
sector_t* sec = &sectors[id];
mtag_t curtag = Tag_FGet(&sec->tags);
if (curtag == tag)
return;
Taggroup_Remove(tags_sectors, curtag, id);
Taggroup_Add(tags_sectors, tag, id);
Tag_FSet(&sec->tags, tag);
}

127
src/taglist.h Normal file
View File

@ -0,0 +1,127 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// Copyright (C) 2020 by Nev3r.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file taglist.h
/// \brief Tag iteration and reading functions and macros' declarations.
#ifndef __R_TAGLIST__
#define __R_TAGLIST__
#include "doomtype.h"
typedef INT16 mtag_t;
#define MAXTAGS UINT16_MAX
#define MTAG_GLOBAL -1
/// Multitag list. Each taggable element will have its own taglist.
typedef struct
{
mtag_t* tags;
UINT16 count;
} taglist_t;
void Tag_Add (taglist_t* list, const mtag_t tag);
void Tag_FSet (taglist_t* list, const mtag_t tag);
mtag_t Tag_FGet (const taglist_t* list);
boolean Tag_Find (const taglist_t* list, const mtag_t tag);
boolean Tag_Share (const taglist_t* list1, const taglist_t* list2);
boolean Tag_Compare (const taglist_t* list1, const taglist_t* list2);
void Tag_SectorFSet (const size_t id, const mtag_t tag);
/// Taggroup list. It is essentially just an element id list.
typedef struct
{
size_t *elements;
size_t count;
} taggroup_t;
extern taggroup_t* tags_sectors[];
extern taggroup_t* tags_lines[];
extern taggroup_t* tags_mapthings[];
void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id);
void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id);
size_t Taggroup_Find (const taggroup_t *group, const size_t id);
void Taglist_InitGlobalTables(void);
INT32 Tag_Iterate_Sectors (const mtag_t tag, const size_t p);
INT32 Tag_Iterate_Lines (const mtag_t tag, const size_t p);
INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p);
INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag);
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start);
// Use this macro to declare an iterator position variable.
#define TAG_ITER_DECLARECOUNTER(level) size_t ICNT_##level
#define TAG_ITER(level, fn, tag, return_varname) for(ICNT_##level = 0; (return_varname = fn(tag, ICNT_##level)) >= 0; ICNT_##level++)
// Use these macros as wrappers for a taglist iteration.
#define TAG_ITER_SECTORS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Sectors, tag, return_varname)
#define TAG_ITER_LINES(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Lines, tag, return_varname)
#define TAG_ITER_THINGS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Things, tag, return_varname)
/* ITERATION MACROS
TAG_ITER_DECLARECOUNTER must be used before using the iterators.
'level':
For each nested iteration, an additional TAG_ITER_DECLARECOUNTER
must be used with a different level number to avoid conflict with
the outer iterations.
Most cases don't have nested iterations and thus the level is just 0.
'tag':
Pretty much the elements' tag to iterate through.
'return_varname':
Target variable's name to return the iteration results to.
EXAMPLE:
{
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_DECLARECOUNTER(1); // For the nested iteration.
size_t li;
size_t sec;
INT32 tag1 = 4;
...
TAG_ITER_LINES(0, tag1, li)
{
line_t *line = lines + li;
...
if (something)
{
mtag_t tag2 = 8;
// Nested iteration; just make sure the level is higher
// and that it has its own counter declared in scope.
TAG_ITER_SECTORS(1, tag2, sec)
{
sector_t *sector = sectors + sec;
...
}
}
}
}
Notes:
If no elements are found for a given tag, the loop inside won't be executed.
*/
#endif //__R_TAGLIST__