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_telept.c
p_tick.c p_tick.c
p_user.c p_user.c
taglist.c
p_local.h p_local.h
p_maputl.h p_maputl.h
@ -180,6 +181,7 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h p_slopes.h
p_spec.h p_spec.h
p_tick.h p_tick.h
taglist.h
) )
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))

View File

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

View File

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

View File

@ -1608,7 +1608,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
//Hurdler: 3d-floors test //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; ffloor_t * rover;
fixed_t highcut = 0, lowcut = 0; 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) 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)) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
continue; continue;
if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES) 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) 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)) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
continue; continue;
if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES))
@ -2384,7 +2408,7 @@ static void HWR_AddLine(seg_t * line)
if (!line->polyseg && if (!line->polyseg &&
!line->sidedef->midtexture !line->sidedef->midtexture
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors) && ((!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 return; // line is empty, don't even bother
// treat like wide open window instead // treat like wide open window instead
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D 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 && if (!line->polyseg &&
!line->sidedef->midtexture !line->sidedef->midtexture
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors) && ((!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 return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead goto clippass; // treat like wide open window instead

View File

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

View File

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

View File

@ -848,7 +848,7 @@ static int mapthing_get(lua_State *L)
else if(fastcmp(field,"extrainfo")) else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo; number = mt->extrainfo;
else if(fastcmp(field,"tag")) else if(fastcmp(field,"tag"))
number = mt->tag; number = Tag_FGet(&mt->tags);
else if(fastcmp(field,"args")) else if(fastcmp(field,"args"))
{ {
LUA_PushUserdata(L, mt->args, META_THINGARGS); LUA_PushUserdata(L, mt->args, META_THINGARGS);
@ -910,7 +910,7 @@ static int mapthing_set(lua_State *L)
mt->extrainfo = (UINT8)extrainfo; mt->extrainfo = (UINT8)extrainfo;
} }
else if (fastcmp(field,"tag")) 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")) else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else 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->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->scale = player->mo->scale; mt->scale = player->mo->scale;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;

View File

@ -394,8 +394,10 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; 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]; 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; ceiling->type = type;
firstone = 0; firstone = 0;
} }
@ -614,8 +616,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; 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]; sec = &sectors[secnum];
@ -670,7 +674,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
break; break;
} }
ceiling->tag = sec->tag; ceiling->tag = tag;
ceiling->type = type; ceiling->type = type;
} }
return rtn; return rtn;

View File

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

View File

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

View File

@ -1388,7 +1388,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bot) if (player->bot)
return; return;
junk.tag = LE_AXE; Tag_FSet(&junk.tags, LE_AXE);
EV_DoElevator(&junk, bridgeFall, false); EV_DoElevator(&junk, bridgeFall, false);
// scan the remaining thinkers to find koopa // 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) void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force)
{ {
INT32 i; INT32 i;
TAG_ITER_DECLARECOUNTER(0);
// search all sectors for ones with tag // 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 if (!force && ticbased // always let speed fader execute
&& sectors[i].lightingdata && sectors[i].lightingdata

View File

@ -3536,16 +3536,19 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
{ {
sector_t *sector; sector_t *sector;
fixed_t halfheight = thiscam->z + (thiscam->height >> 1); fixed_t halfheight = thiscam->z + (thiscam->height >> 1);
size_t i;
// see if we are in water // see if we are in water
sector = thiscam->subsector->sector; sector = thiscam->subsector->sector;
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1) for (i = 0; i < sector->tags.count; i++)
return true; if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
return true;
if (sector->ffloors) if (sector->ffloors)
{ {
ffloor_t *rover; ffloor_t *rover;
size_t j;
for (rover = sector->ffloors; rover; rover = rover->next) 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)) if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
continue; 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; 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); const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum; INT32 snum;
sector_t *sector; 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]; sector = &sectors[snum];
if (sector->tag != tag)
continue;
sector->floorheight += delta; sector->floorheight += delta;
sector->ceilingheight += delta; sector->ceilingheight += delta;
P_CheckSector(sector, true); P_CheckSector(sector, true);
gotcage = true;
} }
return sectors[tag%numsectors].firsttag != -1; return gotcage;
} }
// Move Boss4's arms to angle // 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) static void P_Boss4DestroyCage(mobj_t *mobj)
{ {
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum, next; INT32 snum;
size_t a; size_t a;
sector_t *sector, *rsec; sector_t *sector, *rsec;
ffloor_t *rover; ffloor_t *rover;
TAG_ITER_DECLARECOUNTER(0);
// This will be the final iteration of sector tag. TAG_ITER_SECTORS(0, tag, snum)
// 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)
{ {
sector = &sectors[snum]; sector = &sectors[snum];
next = sector->nexttag;
sector->nexttag = -1;
if (sector->tag != tag)
continue;
sector->tag = 0;
// Destroy the FOFs. // Destroy the FOFs.
for (a = 0; a < sector->numattached; a++) 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 // Sector special (2,8) allows ANY mobj to trigger a linedef exec
if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8) if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
{ {
sector_t *sec2; sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) 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) if (mobj->scale != mobj->destscale)
@ -10274,14 +10271,19 @@ void P_PushableThinker(mobj_t *mobj)
sec = mobj->subsector->sector; sec = mobj->subsector->sector;
if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight) 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) // else if (GETSECSPECIAL(sec->special, 2) == 8)
{ {
sector_t *sec2; sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) 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 // 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); const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag // Find the corresponding linedef special, using angle as tag
// P_FindSpecialLineFromTag works here now =D line = Tag_FindLineSpecial(9, mthing->angle);
line = P_FindSpecialLineFromTag(9, mthing->angle, -1);
if (line == -1) 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); const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag // 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) if (line == -1)
{ {
@ -12580,17 +12581,20 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
break; break;
} }
case MT_SKYBOX: 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; break;
} }
if (mthing->options & MTF_OBJECTSPECIAL) if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->tag] = mobj; skyboxcenterpnts[tag] = mobj;
else else
skyboxviewpnts[mthing->tag] = mobj; skyboxviewpnts[tag] = mobj;
break; break;
}
case MT_EGGSTATUE: case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA) if (mthing->options & MTF_EXTRA)
{ {

View File

@ -556,10 +556,11 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
polyobj_t *po; polyobj_t *po;
vertex_t dist, sspot; vertex_t dist, sspot;
size_t i; 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; return;
} }
@ -1342,7 +1343,7 @@ void Polyobj_InitLevel(void)
{ {
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue); 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 // move polyobjects to spawn points
@ -2444,10 +2445,11 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
polymove_t *th; polymove_t *th;
size_t i; size_t i;
INT32 start; 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; return false;
} }
@ -2470,7 +2472,7 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
po->thinker = &th->thinker; po->thinker = &th->thinker;
// set fields // set fields
th->polyObjNum = pfdata->polyObjNum; th->polyObjNum = tag;
th->distance = 0; th->distance = 0;
th->speed = pfdata->speed; th->speed = pfdata->speed;
th->angle = pfdata->angle; th->angle = pfdata->angle;

View File

@ -923,7 +923,7 @@ static void UnArchiveFFloors(const sector_t *ss)
static void ArchiveSectors(void) static void ArchiveSectors(void)
{ {
size_t i; size_t i, j;
const sector_t *ss = sectors; const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors; const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3;
@ -961,10 +961,8 @@ static void ArchiveSectors(void)
if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) if (ss->ceilingpic_angle != spawnss->ceilingpic_angle)
diff2 |= SD_CEILANG; diff2 |= SD_CEILANG;
if (ss->tag != spawnss->tag) if (!Tag_Compare(&ss->tags, &spawnss->tags))
diff2 |= SD_TAG; diff2 |= SD_TAG;
if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag)
diff3 |= SD_TAGLIST;
if (ss->extra_colormap != spawnss->extra_colormap) if (ss->extra_colormap != spawnss->extra_colormap)
diff3 |= SD_COLORMAP; diff3 |= SD_COLORMAP;
@ -1012,12 +1010,11 @@ static void ArchiveSectors(void)
WRITEANGLE(save_p, ss->floorpic_angle); WRITEANGLE(save_p, ss->floorpic_angle);
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
WRITEANGLE(save_p, ss->ceilingpic_angle); WRITEANGLE(save_p, ss->ceilingpic_angle);
if (diff2 & SD_TAG) // save only the tag if (diff2 & SD_TAG)
WRITEINT16(save_p, ss->tag); {
if (diff3 & SD_TAGLIST) // save both firsttag and nexttag WRITEUINT32(save_p, ss->tags.count);
{ // either of these could be changed even if tag isn't for (j = 0; j < ss->tags.count; j++)
WRITEINT32(save_p, ss->firsttag); WRITEINT16(save_p, ss->tags.tags[j]);
WRITEINT32(save_p, ss->nexttag);
} }
if (diff3 & SD_COLORMAP) if (diff3 & SD_COLORMAP)
@ -1035,7 +1032,7 @@ static void ArchiveSectors(void)
static void UnArchiveSectors(void) static void UnArchiveSectors(void)
{ {
UINT16 i; UINT16 i, j;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3;
for (;;) for (;;)
{ {
@ -1089,13 +1086,29 @@ static void UnArchiveSectors(void)
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
sectors[i].ceilingpic_angle = READANGLE(save_p); sectors[i].ceilingpic_angle = READANGLE(save_p);
if (diff2 & SD_TAG) 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); size_t ncount = READUINT32(save_p);
sectors[i].nexttag = READINT32(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) if (diff3 & SD_COLORMAP)
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
if (diff3 & SD_CRUMBLESTATE) if (diff3 & SD_CRUMBLESTATE)

View File

@ -82,6 +82,8 @@
#include "fastcmp.h" // textmap parsing #include "fastcmp.h" // textmap parsing
#include "taglist.h"
// //
// Map MD5, calculated on level load. // Map MD5, calculated on level load.
// Sent to clients in PT_SERVERINFO. // Sent to clients in PT_SERVERINFO.
@ -963,8 +965,6 @@ static void P_LoadVertices(UINT8 *data)
static void P_InitializeSector(sector_t *ss) static void P_InitializeSector(sector_t *ss)
{ {
ss->nexttag = ss->firsttag = -1;
memset(&ss->soundorg, 0, sizeof(ss->soundorg)); memset(&ss->soundorg, 0, sizeof(ss->soundorg));
ss->validcount = 0; ss->validcount = 0;
@ -1035,7 +1035,7 @@ static void P_LoadSectors(UINT8 *data)
ss->lightlevel = SHORT(ms->lightlevel); ss->lightlevel = SHORT(ms->lightlevel);
ss->special = SHORT(ms->special); 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->floor_xoffs = ss->floor_yoffs = 0;
ss->ceiling_xoffs = ss->ceiling_yoffs = 0; ss->ceiling_xoffs = ss->ceiling_yoffs = 0;
@ -1077,7 +1077,6 @@ static void P_InitializeLinedef(line_t *ld)
#ifdef WALLSPLATS #ifdef WALLSPLATS
ld->splats = NULL; ld->splats = NULL;
#endif #endif
ld->firsttag = ld->nexttag = -1;
ld->polyobj = NULL; ld->polyobj = NULL;
ld->text = NULL; ld->text = NULL;
@ -1149,7 +1148,7 @@ static void P_LoadLinedefs(UINT8 *data)
{ {
ld->flags = SHORT(mld->flags); ld->flags = SHORT(mld->flags);
ld->special = SHORT(mld->special); 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->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT; ld->alpha = FRACUNIT;
@ -1342,7 +1341,7 @@ static void P_LoadSidedefs(UINT8 *data)
|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F')) || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F'))
sd->toptexture = axtoi(msd->toptexture); sd->toptexture = axtoi(msd->toptexture);
else 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->midtexture = R_TextureNumForName(msd->midtexture);
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
@ -1382,8 +1381,8 @@ static void P_LoadThings(UINT8 *data)
mt->type = READUINT16(data); mt->type = READUINT16(data);
mt->options = READUINT16(data); mt->options = READUINT16(data);
mt->extrainfo = (UINT8)(mt->type >> 12); mt->extrainfo = (UINT8)(mt->type >> 12);
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT; mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;
@ -1519,7 +1518,17 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
else if (fastcmp(param, "special")) else if (fastcmp(param, "special"))
sectors[i].special = atol(val); sectors[i].special = atol(val);
else if (fastcmp(param, "id")) 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")) else if (fastcmp(param, "xpanningfloor"))
sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val)); sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "ypanningfloor")) 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) static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "id")) 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")) else if (fastcmp(param, "special"))
lines[i].special = atol(val); lines[i].special = atol(val);
else if (fastcmp(param, "v1")) 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) static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "id")) if (fastcmp(param, "id"))
mapthings[i].tag = atol(val); Tag_FSet(&mapthings[i].tags, atol(val));
if (fastcmp(param, "x")) 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); mapthings[i].x = atol(val);
else if (fastcmp(param, "y")) else if (fastcmp(param, "y"))
mapthings[i].y = atol(val); mapthings[i].y = atol(val);
@ -1824,7 +1853,7 @@ static void P_LoadTextmap(void)
sc->lightlevel = 255; sc->lightlevel = 255;
sc->special = 0; sc->special = 0;
sc->tag = 0; Tag_FSet(&sc->tags, 0);
sc->floor_xoffs = sc->floor_yoffs = 0; sc->floor_xoffs = sc->floor_yoffs = 0;
sc->ceiling_xoffs = sc->ceiling_yoffs = 0; sc->ceiling_xoffs = sc->ceiling_yoffs = 0;
@ -1842,6 +1871,7 @@ static void P_LoadTextmap(void)
textmap_colormap.fadeend = 31; textmap_colormap.fadeend = 31;
textmap_colormap.flags = 0; textmap_colormap.flags = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc); P_InitializeSector(sc);
if (textmap_colormap.used) if (textmap_colormap.used)
{ {
@ -1858,7 +1888,8 @@ static void P_LoadTextmap(void)
ld->v1 = ld->v2 = NULL; ld->v1 = ld->v2 = NULL;
ld->flags = 0; ld->flags = 0;
ld->special = 0; ld->special = 0;
ld->tag = 0; Tag_FSet(&ld->tags, 0);
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT; ld->alpha = FRACUNIT;
@ -1906,8 +1937,8 @@ static void P_LoadTextmap(void)
mt->options = 0; mt->options = 0;
mt->z = 0; mt->z = 0;
mt->extrainfo = 0; mt->extrainfo = 0;
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT; mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL; 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. //For maps in binary format, converts setup of specials to UDMF format.
static void P_ConvertBinaryMap(void) static void P_ConvertBinaryMap(void)
{ {
@ -2955,14 +2962,28 @@ static void P_ConvertBinaryMap(void)
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
{ {
mtag_t tag = Tag_FGet(&lines[i].tags);
switch (lines[i].special) switch (lines[i].special)
{ {
case 20: //PolyObject first line 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 //PolyObject ID
lines[i].args[0] = lines[i].tag; lines[i].args[0] = tag;
//Default: Invisible planes //Default: Invisible planes
lines[i].args[3] |= TMPF_INVISIBLEPLANES; 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)); 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; break;
case 447: //Change colormap 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) if (lines[i].flags & ML_EFFECT3)
lines[i].args[2] |= TMCF_RELATIVE; lines[i].args[2] |= TMCF_RELATIVE;
if (lines[i].flags & ML_EFFECT1) 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[1]].rowoffset >> FRACBITS)
: abs(sides[lines[i].sidenum[0]].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) if (lines[i].flags & ML_EFFECT4)
lines[i].args[2] = speed; lines[i].args[2] = speed;
else else
@ -3044,10 +3065,10 @@ static void P_ConvertBinaryMap(void)
break; break;
} }
case 456: //Stop fading colormap case 456: //Stop fading colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
break; break;
case 606: //Colormap case 606: //Colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
break; break;
case 700: //Slope front sector floor case 700: //Slope front sector floor
case 701: //Slope front sector ceiling case 701: //Slope front sector ceiling
@ -3088,7 +3109,7 @@ static void P_ConvertBinaryMap(void)
else if (lines[i].special == 715) else if (lines[i].special == 715)
lines[i].args[0] = TMSP_BACKCEILING; lines[i].args[0] = TMSP_BACKCEILING;
lines[i].args[1] = lines[i].tag; lines[i].args[1] = tag;
if (lines[i].flags & ML_EFFECT6) if (lines[i].flags & ML_EFFECT6)
{ {
@ -3120,9 +3141,9 @@ static void P_ConvertBinaryMap(void)
case 721: //Copy front side ceiling slope case 721: //Copy front side ceiling slope
case 722: //Copy front side floor and ceiling slope case 722: //Copy front side floor and ceiling slope
if (lines[i].special != 721) if (lines[i].special != 721)
lines[i].args[0] = lines[i].tag; lines[i].args[0] = tag;
if (lines[i].special != 720) if (lines[i].special != 720)
lines[i].args[1] = lines[i].tag; lines[i].args[1] = tag;
lines[i].special = 720; lines[i].special = 720;
break; break;
case 900: //Translucent wall (10%) case 900: //Translucent wall (10%)
@ -3155,21 +3176,39 @@ static void P_ConvertBinaryMap(void)
switch (mapthings[i].type) switch (mapthings[i].type)
{ {
case 750: case 750:
Tag_Add(&mapthings[i].tags, mapthings[i].angle);
break;
case 760: case 760:
case 761: case 761:
mapthings[i].tag = mapthings[i].angle; Tag_FSet(&mapthings[i].tags, mapthings[i].angle);
break; break;
case 762: 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) if (firstline != -1)
lines[firstline].args[3] |= TMPF_CRUSH; lines[firstline].args[3] |= TMPF_CRUSH;
mapthings[i].tag = mapthings[i].angle;
mapthings[i].type = 761; mapthings[i].type = 761;
break; break;
} }
case 780: case 780:
mapthings[i].tag = mapthings[i].extrainfo; Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo);
break; break;
default: default:
break; break;
@ -3243,6 +3282,7 @@ static boolean P_LoadMapFromFile(void)
{ {
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum); virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
size_t i;
udmf = textmap != NULL; udmf = textmap != NULL;
if (!P_LoadMapData(virt)) if (!P_LoadMapData(virt))
@ -3252,7 +3292,7 @@ static boolean P_LoadMapFromFile(void)
P_LinkMapData(); P_LinkMapData();
P_InitTagLists(); // Create xref tables for tags Taglist_InitGlobalTables();
if (!udmf) if (!udmf)
P_ConvertBinaryMap(); P_ConvertBinaryMap();
@ -3266,6 +3306,10 @@ static boolean P_LoadMapFromFile(void)
memcpy(spawnlines, lines, numlines * sizeof(*lines)); memcpy(spawnlines, lines, numlines * sizeof(*lines));
memcpy(spawnsides, sides, numsides * sizeof(*sides)); 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); P_MakeMapMD5(virt, &mapmd5);
vres_Free(virt); vres_Free(virt);

View File

@ -139,7 +139,7 @@ void T_DynamicSlopeVert (dynplanethink_t* th)
INT32 l; INT32 l;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
l = P_FindSpecialLineFromTag(799, th->tags[i], -1); l = Tag_FindLineSpecial(799, th->tags[i]);
if (l != -1) { if (l != -1) {
th->vex[i].z = lines[l].frontsector->floorheight; 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); P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL);
} }
} }
if(!line->tag)
return;
} }
/// Creates a new slope from three mapthings with the specified IDs /// 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! if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue; continue;
if (!vertices[0] && mt->tag == tag1) if (!vertices[0] && Tag_Find(&mt->tags, tag1))
vertices[0] = mt; vertices[0] = mt;
else if (!vertices[1] && mt->tag == tag2) else if (!vertices[1] && Tag_Find(&mt->tags, tag2))
vertices[1] = mt; vertices[1] = mt;
else if (!vertices[2] && mt->tag == tag3) else if (!vertices[2] && Tag_Find(&mt->tags, tag3))
vertices[2] = mt; vertices[2] = mt;
} }
@ -549,11 +546,11 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling)
{ {
INT32 i; INT32 i;
pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope; pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope;
TAG_ITER_DECLARECOUNTER(0);
if (!tag || *secslope) if (!tag || *secslope)
return false; return false;
TAG_ITER_SECTORS(0, tag, i)
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;)
{ {
pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope; pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope;
if (srcslope) 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_FindLowestCeilingSurrounding(sector_t *sec);
fixed_t P_FindHighestCeilingSurrounding(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); INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_SetupSignExit(player_t *player); 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); 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_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
void P_RunNightserizeExecutors(mobj_t *actor); void P_RunNightserizeExecutors(mobj_t *actor);
void P_RunDeNightserizeExecutors(mobj_t *actor); void P_RunDeNightserizeExecutors(mobj_t *actor);
void P_RunNightsLapExecutors(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; postimg_t *type;
INT32 *param; INT32 *param;
fixed_t pviewheight; fixed_t pviewheight;
size_t i;
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
pviewheight = player->mo->z + player->mo->height - player->viewheight; 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...) // see if we are in heat (no, not THAT kind of heat...)
for (i = 0; i < sector->tags.count; i++)
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
*type = postimg_heat;
else if (sector->ffloors)
{ {
ffloor_t *rover; if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
fixed_t topheight;
fixed_t bottomheight;
for (rover = sector->ffloors; rover; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS)) *type = postimg_heat;
continue; 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); for (rover = sector->ffloors; rover; rover = rover->next)
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); {
size_t j;
if (pviewheight >= topheight || pviewheight <= bottomheight) if (!(rover->flags & FF_EXISTS))
continue; continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y);
*type = postimg_heat; 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) static INT32 P_GetMinecartSpecialLine(sector_t *sec)
{ {
INT32 line = -1; INT32 line = -1;
size_t i;
if (!sec) if (!sec)
return line; return line;
if (sec->tag != 0) for (i = 0; i < sec->tags.count; i++)
line = P_FindSpecialLineFromTag(16, sec->tag, -1); 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. // Also try for lines facing the sector itself, with tag 0.
for (i = 0; i < sec->linecount; i++)
{ {
UINT32 i; line_t *li = sec->lines[i];
for (i = 0; i < sec->linecount; i++) if (Tag_Find(&li->tags, 0) && li->special == 16 && li->frontsector == sec)
{ line = li - lines;
line_t *li = sec->lines[i];
if (li->tag == 0 && li->special == 16 && li->frontsector == sec)
line = li - lines;
}
} }
return line; return line;
@ -12297,12 +12314,14 @@ void P_PlayerThink(player_t *player)
sector_t *controlsec; sector_t *controlsec;
for (j=0; j<numsectors; j++) for (j=0; j<numsectors; j++)
{ {
mtag_t sectag = Tag_FGet(&sectors[j].tags);
controlsec = NULL; controlsec = NULL;
// Does this sector have a water linedef? // Does this sector have a water linedef?
for (i=0; i<numlines;i++) for (i=0; i<numlines;i++)
{ {
mtag_t linetag = Tag_FGet(&lines[i].tags);
if ((lines[i].special == 121 || lines[i].special == 123) if ((lines[i].special == 121 || lines[i].special == 123)
&& lines[i].tag == sectors[j].tag) && linetag == sectag)
{ {
controlsec = lines[i].frontsector; controlsec = lines[i].frontsector;
break; break;
@ -12311,15 +12330,16 @@ void P_PlayerThink(player_t *player)
if (i < numlines && controlsec) if (i < numlines && controlsec)
{ {
controlsectag = Tag_FGet(&controlsec->tags);
// Does this sector have a colormap? // Does this sector have a colormap?
for (i=0; i<numlines;i++) for (i=0; i<numlines;i++)
{ {
if (lines[i].special == 606 && lines[i].tag == controlsec->tag) if (lines[i].special == 606 && linetag == controlsectag)
break; break;
} }
if (i == numlines) 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_local.h" // camera
#include "p_slopes.h" #include "p_slopes.h"
#include "z_zone.h" // Check R_Prep3DFloors #include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h"
seg_t *curline; seg_t *curline;
side_t *sidedef; side_t *sidedef;
@ -374,7 +375,7 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
// Consider colormaps // Consider colormaps
&& back->extra_colormap == front->extra_colormap && back->extra_colormap == front->extra_colormap
&& ((!front->ffloors && !back->ffloors) && ((!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 // Portal line
if (line->linedef->special == 40 && line->side == 0) 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) if (portalrender < cv_maxportals.value)
{ {
// Find the other side! size_t p;
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1); mtag_t tag = Tag_FGet(&line->linedef->tags);
if (line->linedef == &lines[line2]) INT32 li1 = line->linedef-lines;
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2); INT32 li2;
if (line2 >= 0) // found it!
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 // Skip invalid lines.
//return; // Don't fill in that space now! if ((tag != Tag_FGet(&lines[li2].tags)) || (lines[li1].special != lines[li2].special) || (li1 == li2))
continue;
Portal_Add2Lines(li1, li2, x1, x2);
goto clipsolid; 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? // Single sided line?
@ -483,7 +488,7 @@ static void R_AddLine(seg_t *line)
if (!line->polyseg && if (!line->polyseg &&
!line->sidedef->midtexture !line->sidedef->midtexture
&& ((!frontsector->ffloors && !backsector->ffloors) && ((!frontsector->ffloors && !backsector->ffloors)
|| (frontsector->tag == backsector->tag))) || Tag_Compare(&frontsector->tags, &backsector->tags)))
return; // line is empty, don't even bother return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead goto clippass; // treat like wide open window instead

View File

@ -28,6 +28,8 @@
#include "m_aatree.h" #include "m_aatree.h"
#endif #endif
#include "taglist.h"
// //
// ClipWallSegment // ClipWallSegment
// Clips the given range of columns // Clips the given range of columns
@ -281,8 +283,7 @@ typedef struct sector_s
INT32 ceilingpic; INT32 ceilingpic;
INT16 lightlevel; INT16 lightlevel;
INT16 special; INT16 special;
UINT16 tag; taglist_t tags;
INT32 nexttag, firsttag; // for fast tag searches
// origin for any sounds played by the sector // origin for any sounds played by the sector
// also considered the center for e.g. Mario blocks // also considered the center for e.g. Mario blocks
@ -389,7 +390,7 @@ typedef struct line_s
// Animation related. // Animation related.
INT16 flags; INT16 flags;
INT16 special; INT16 special;
INT16 tag; taglist_t tags;
INT32 args[NUMLINEARGS]; INT32 args[NUMLINEARGS];
char *stringargs[NUMLINESTRINGARGS]; char *stringargs[NUMLINESTRINGARGS];
@ -412,7 +413,6 @@ typedef struct line_s
#if 1//#ifdef WALLSPLATS #if 1//#ifdef WALLSPLATS
void *splats; // wallsplat_t list void *splats; // wallsplat_t list
#endif #endif
INT32 firsttag, nexttag; // improves searches for tags.
polyobj_t *polyobj; // Belongs to a polyobject? 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. 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_local.h" // Camera...
#include "p_slopes.h" #include "p_slopes.h"
#include "console.h" // con_clipviewtop #include "console.h" // con_clipviewtop
#include "taglist.h"
// OPTIMIZE: closed two sided lines as single sided // OPTIMIZE: closed two sided lines as single sided
@ -2067,7 +2068,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->floorlightsec != frontsector->floorlightsec || backsector->floorlightsec != frontsector->floorlightsec
//SoM: 4/3/2000: Check for colormaps //SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap || 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; markfloor = true;
} }
@ -2098,7 +2099,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->ceilinglightsec != frontsector->ceilinglightsec || backsector->ceilinglightsec != frontsector->ceilinglightsec
//SoM: 4/3/2000: Check for colormaps //SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap || 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; markceiling = true;
} }
@ -2188,7 +2189,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
rw_bottomtexturemid += sidedef->rowoffset; rw_bottomtexturemid += sidedef->rowoffset;
// allocate space for masked texture tables // 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 *rover;
ffloor_t *r2; ffloor_t *r2;
@ -2230,6 +2231,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (r2 = frontsector->ffloors; r2; r2 = r2->next) 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)) if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue; continue;
@ -2285,6 +2289,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (r2 = backsector->ffloors; r2; r2 = r2->next) 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)) if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue; 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__