mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-13 07:57:52 +00:00
- uncouple sector tag storage from the sector data to allow multiple tags per sector.
Tags are now handled by a tag manager class which stores sector/tag pairs. This way multiple entries can be added per sector. Since UDMF does not have any arrays the additional tags are stored as a space separated string as 'MoreIDs'.
This commit is contained in:
parent
6326cd74b4
commit
b921157f57
21 changed files with 274 additions and 96 deletions
|
@ -49,6 +49,7 @@
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
|
#include "p_tags.h"
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
|
|
||||||
|
@ -551,8 +552,8 @@ void SetCompatibilityParams()
|
||||||
{
|
{
|
||||||
if ((unsigned)CompatParams[i + 1] < (unsigned)numsectors)
|
if ((unsigned)CompatParams[i + 1] < (unsigned)numsectors)
|
||||||
{
|
{
|
||||||
sectors[CompatParams[i + 1]].ClearTags();
|
// this assumes that the sector does not have any tags yet!
|
||||||
sectors[CompatParams[i + 1]].SetMainTag(CompatParams[i + 2]);
|
tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]);
|
||||||
}
|
}
|
||||||
i += 3;
|
i += 3;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1165,7 +1165,7 @@ void FParser::SF_ObjSector(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
t_return.type = svt_int;
|
t_return.type = svt_int;
|
||||||
t_return.value.i = mo ? mo->Sector->GetMainTag() : 0; // nullptr check
|
t_return.value.i = mo ? tagManager.GetFirstSectorTag(mo->Sector) : 0; // nullptr check
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -4312,7 +4312,7 @@ void FParser::SF_KillInSector()
|
||||||
|
|
||||||
while ((mo=it.Next()))
|
while ((mo=it.Next()))
|
||||||
{
|
{
|
||||||
if (mo->flags3&MF3_ISMONSTER && mo->Sector->HasTag(tag)) P_DamageMobj(mo, NULL, NULL, 1000000, NAME_Massacre);
|
if (mo->flags3&MF3_ISMONSTER && tagManager.SectorHasTag(mo->Sector, tag)) P_DamageMobj(mo, NULL, NULL, 1000000, NAME_Massacre);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -636,7 +636,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
|
||||||
}
|
}
|
||||||
else if ((sec->special & 0xFF) == Scroll_StrifeCurrent)
|
else if ((sec->special & 0xFF) == Scroll_StrifeCurrent)
|
||||||
{
|
{
|
||||||
int anglespeed = sec->GetMainTag() - 100;
|
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
|
||||||
fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);
|
fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);
|
||||||
angle_t finean = (anglespeed / 10) << (32-3);
|
angle_t finean = (anglespeed / 10) << (32-3);
|
||||||
finean >>= ANGLETOFINESHIFT;
|
finean >>= ANGLETOFINESHIFT;
|
||||||
|
|
|
@ -326,6 +326,7 @@ xx(Arg4)
|
||||||
xx(Arg0Str)
|
xx(Arg0Str)
|
||||||
xx(Arg1Str)
|
xx(Arg1Str)
|
||||||
xx(Id)
|
xx(Id)
|
||||||
|
xx(MoreIds)
|
||||||
xx(V1)
|
xx(V1)
|
||||||
xx(V2)
|
xx(V2)
|
||||||
|
|
||||||
|
|
|
@ -3211,7 +3211,7 @@ do_count:
|
||||||
if (actor->health > 0 &&
|
if (actor->health > 0 &&
|
||||||
(kind == NULL || actor->IsA (kind)))
|
(kind == NULL || actor->IsA (kind)))
|
||||||
{
|
{
|
||||||
if (actor->Sector->HasTag(tag) || tag == -1)
|
if (tag == -1 || tagManager.SectorHasTag(actor->Sector, tag))
|
||||||
{
|
{
|
||||||
// Don't count items in somebody's inventory
|
// Don't count items in somebody's inventory
|
||||||
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
|
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
|
||||||
|
@ -3231,7 +3231,7 @@ do_count:
|
||||||
if (actor->health > 0 &&
|
if (actor->health > 0 &&
|
||||||
(kind == NULL || actor->IsA (kind)))
|
(kind == NULL || actor->IsA (kind)))
|
||||||
{
|
{
|
||||||
if (actor->Sector->HasTag(tag) || tag == -1)
|
if (tag == -1 || tagManager.SectorHasTag(actor->Sector, tag))
|
||||||
{
|
{
|
||||||
// Don't count items in somebody's inventory
|
// Don't count items in somebody's inventory
|
||||||
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
|
if (!actor->IsKindOf (RUNTIME_CLASS(AInventory)) ||
|
||||||
|
|
|
@ -838,7 +838,7 @@ void EV_StopLightEffect (int tag)
|
||||||
|
|
||||||
while ((effect = iterator.Next()) != NULL)
|
while ((effect = iterator.Next()) != NULL)
|
||||||
{
|
{
|
||||||
if (effect->GetSector()->HasTag(tag))
|
if (tagManager.SectorHasTag(effect->GetSector(), tag))
|
||||||
{
|
{
|
||||||
effect->Destroy();
|
effect->Destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,7 +278,7 @@ static void RemoveTaggedSectors(extsector_t::linked::plane &scrollplane, int tag
|
||||||
{
|
{
|
||||||
for(int i = scrollplane.Sectors.Size()-1; i>=0; i--)
|
for(int i = scrollplane.Sectors.Size()-1; i>=0; i--)
|
||||||
{
|
{
|
||||||
if (scrollplane.Sectors[i].Sector->HasTag(tag))
|
if (tagManager.SectorHasTag(scrollplane.Sectors[i].Sector, tag))
|
||||||
{
|
{
|
||||||
scrollplane.Sectors.Delete(i);
|
scrollplane.Sectors.Delete(i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1266,7 +1266,7 @@ FUNC(LS_Thing_Destroy)
|
||||||
while (actor)
|
while (actor)
|
||||||
{
|
{
|
||||||
AActor *temp = iterator.Next ();
|
AActor *temp = iterator.Next ();
|
||||||
if (actor->flags & MF_SHOOTABLE && actor->Sector->HasTag(arg2))
|
if (actor->flags & MF_SHOOTABLE && tagManager.SectorHasTag(actor->Sector, arg2))
|
||||||
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
|
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
|
||||||
actor = temp;
|
actor = temp;
|
||||||
}
|
}
|
||||||
|
@ -1279,7 +1279,7 @@ FUNC(LS_Thing_Destroy)
|
||||||
while (actor)
|
while (actor)
|
||||||
{
|
{
|
||||||
AActor *temp = iterator.Next ();
|
AActor *temp = iterator.Next ();
|
||||||
if (actor->flags & MF_SHOOTABLE && (arg2 == 0 || actor->Sector->HasTag(arg2)))
|
if (actor->flags & MF_SHOOTABLE && (arg2 == 0 || tagManager.SectorHasTag(actor->Sector, arg2)))
|
||||||
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
|
P_DamageMobj (actor, NULL, it, arg1 ? TELEFRAG_DAMAGE : actor->health, NAME_None);
|
||||||
actor = temp;
|
actor = temp;
|
||||||
}
|
}
|
||||||
|
@ -2169,7 +2169,7 @@ static void SetScroller (int tag, DScroller::EScrollType type, fixed_t dx, fixed
|
||||||
{
|
{
|
||||||
if (scroller->IsType (type))
|
if (scroller->IsType (type))
|
||||||
{
|
{
|
||||||
if (sectors[scroller->GetAffectee ()].HasTag(tag))
|
if (tagManager.SectorHasTag(scroller->GetAffectee (), tag))
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
scroller->SetRate (dx, dy);
|
scroller->SetRate (dx, dy);
|
||||||
|
|
|
@ -3437,7 +3437,7 @@ void AActor::Tick ()
|
||||||
}
|
}
|
||||||
else if (scrolltype == Scroll_StrifeCurrent)
|
else if (scrolltype == Scroll_StrifeCurrent)
|
||||||
{ // Strife scroll special
|
{ // Strife scroll special
|
||||||
int anglespeed = sec->GetMainTag() - 100;
|
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
|
||||||
fixed_t carryspeed = DivScale32 (anglespeed % 10, 16*CARRYFACTOR);
|
fixed_t carryspeed = DivScale32 (anglespeed % 10, 16*CARRYFACTOR);
|
||||||
angle_t fineangle = (anglespeed / 10) << (32-3);
|
angle_t fineangle = (anglespeed / 10) << (32-3);
|
||||||
fineangle >>= ANGLETOFINESHIFT;
|
fineangle >>= ANGLETOFINESHIFT;
|
||||||
|
|
|
@ -348,9 +348,13 @@ void P_SerializeWorld (FArchive &arc)
|
||||||
{
|
{
|
||||||
arc << sec->lightlevel;
|
arc << sec->lightlevel;
|
||||||
}
|
}
|
||||||
arc << sec->special
|
arc << sec->special;
|
||||||
<< sec->tag
|
if (SaveVersion < 4523)
|
||||||
<< sec->soundtraversed
|
{
|
||||||
|
short tag;
|
||||||
|
arc << tag;
|
||||||
|
}
|
||||||
|
arc << sec->soundtraversed
|
||||||
<< sec->seqType
|
<< sec->seqType
|
||||||
<< sec->friction
|
<< sec->friction
|
||||||
<< sec->movefactor
|
<< sec->movefactor
|
||||||
|
|
|
@ -825,45 +825,6 @@ sector_t *sector_t::GetHeightSec() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sector_t::HasTag(int checktag) const
|
|
||||||
{
|
|
||||||
return tag == checktag;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sector_t::HasTags() const
|
|
||||||
{
|
|
||||||
return tag != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sector_t::SetMainTag(int tagnum)
|
|
||||||
{
|
|
||||||
tag = tagnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sector_t::GetMainTag() const
|
|
||||||
{
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sector_t::ClearTags()
|
|
||||||
{
|
|
||||||
tag = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sector_t::HashTags()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=numsectors; --i>=0; ) // Initially make all slots empty.
|
|
||||||
sectors[i].firsttag = -1;
|
|
||||||
for (i=numsectors; --i>=0; ) // Proceed from last to first sector
|
|
||||||
{ // so that lower sectors appear first
|
|
||||||
int j = (unsigned) sectors[i].tag % (unsigned) numsectors; // Hash func
|
|
||||||
sectors[i].nexttag = sectors[j].firsttag; // Prepend sector to chain
|
|
||||||
sectors[j].firsttag = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void line_t::SetMainId(int newid)
|
void line_t::SetMainId(int newid)
|
||||||
{
|
{
|
||||||
id = newid;
|
id = newid;
|
||||||
|
|
|
@ -1513,7 +1513,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
|
||||||
else // [RH] Translate to new sector special
|
else // [RH] Translate to new sector special
|
||||||
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
|
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
|
||||||
ss->secretsector = !!(ss->special&SECRET_MASK);
|
ss->secretsector = !!(ss->special&SECRET_MASK);
|
||||||
ss->SetMainTag(LittleShort(ms->tag));
|
tagManager.AddSectorTag(i, LittleShort(ms->tag));
|
||||||
ss->thinglist = NULL;
|
ss->thinglist = NULL;
|
||||||
ss->touching_thinglist = NULL; // phares 3/14/98
|
ss->touching_thinglist = NULL; // phares 3/14/98
|
||||||
ss->seqType = defSeqType;
|
ss->seqType = defSeqType;
|
||||||
|
@ -2493,7 +2493,7 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmaps
|
||||||
|
|
||||||
for (s = 0; s < numsectors; s++)
|
for (s = 0; s < numsectors; s++)
|
||||||
{
|
{
|
||||||
if (sectors[s].HasTag(tag))
|
if (tagManager.SectorHasTag(s, tag))
|
||||||
{
|
{
|
||||||
if (!colorgood) color = sectors[s].ColorMap->Color;
|
if (!colorgood) color = sectors[s].ColorMap->Color;
|
||||||
if (!foggood) fog = sectors[s].ColorMap->Fade;
|
if (!foggood) fog = sectors[s].ColorMap->Fade;
|
||||||
|
@ -3129,9 +3129,9 @@ static void P_GroupLines (bool buildmap)
|
||||||
{
|
{
|
||||||
if (sector->linecount == 0)
|
if (sector->linecount == 0)
|
||||||
{
|
{
|
||||||
Printf ("Sector %i (tag %i) has no lines\n", i, sector->GetMainTag());
|
Printf ("Sector %i (tag %i) has no lines\n", i, tagManager.GetFirstSectorTag(sector));
|
||||||
// 0 the sector's tag so that no specials can use it
|
// 0 the sector's tag so that no specials can use it
|
||||||
sector->ClearTags();
|
tagManager.RemoveSectorTags(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3208,7 +3208,7 @@ static void P_GroupLines (bool buildmap)
|
||||||
// [RH] Moved this here
|
// [RH] Moved this here
|
||||||
times[4].Clock();
|
times[4].Clock();
|
||||||
// killough 1/30/98: Create xref tables for tags
|
// killough 1/30/98: Create xref tables for tags
|
||||||
sector_t::HashTags();
|
tagManager.HashTags();
|
||||||
line_t::HashIds();
|
line_t::HashIds();
|
||||||
times[4].Unclock();
|
times[4].Unclock();
|
||||||
|
|
||||||
|
@ -3340,6 +3340,7 @@ void P_FreeLevelData ()
|
||||||
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
|
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
|
||||||
SN_StopAllSequences ();
|
SN_StopAllSequences ();
|
||||||
DThinker::DestroyAllThinkers ();
|
DThinker::DestroyAllThinkers ();
|
||||||
|
tagManager.Clear();
|
||||||
level.total_monsters = level.total_items = level.total_secrets =
|
level.total_monsters = level.total_items = level.total_secrets =
|
||||||
level.killed_monsters = level.found_items = level.found_secrets =
|
level.killed_monsters = level.found_items = level.found_secrets =
|
||||||
wminfo.maxfrags = 0;
|
wminfo.maxfrags = 0;
|
||||||
|
|
|
@ -1741,7 +1741,7 @@ static void P_SpawnScrollers(void)
|
||||||
if (lines[i].special == Sector_CopyScroller)
|
if (lines[i].special == Sector_CopyScroller)
|
||||||
{
|
{
|
||||||
// don't allow copying the scroller if the sector has the same tag as it would just duplicate it.
|
// don't allow copying the scroller if the sector has the same tag as it would just duplicate it.
|
||||||
if (lines[i].frontsector->HasTag(lines[i].args[0]))
|
if (tagManager.SectorHasTag(lines[i].frontsector, lines[i].args[0]))
|
||||||
{
|
{
|
||||||
copyscrollers.Push(i);
|
copyscrollers.Push(i);
|
||||||
}
|
}
|
||||||
|
@ -2149,7 +2149,7 @@ DPusher::DPusher (DPusher::EPusher type, line_t *l, int magnitude, int angle,
|
||||||
|
|
||||||
int DPusher::CheckForSectorMatch (EPusher type, int tag)
|
int DPusher::CheckForSectorMatch (EPusher type, int tag)
|
||||||
{
|
{
|
||||||
if (m_Type == type && sectors[m_Affectee].HasTag(tag))
|
if (m_Type == type && tagManager.SectorHasTag(m_Affectee, tag))
|
||||||
return m_Affectee;
|
return m_Affectee;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
168
src/p_tags.cpp
168
src/p_tags.cpp
|
@ -35,13 +35,163 @@
|
||||||
|
|
||||||
|
|
||||||
#include "p_tags.h"
|
#include "p_tags.h"
|
||||||
|
#include "c_dispatch.h"
|
||||||
|
|
||||||
|
FTagManager tagManager;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static inline int sectindex(const sector_t *sector)
|
||||||
|
{
|
||||||
|
return (int)(intptr_t)(sector - sectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FTagManager::AddSectorTag(int sector, int tag)
|
||||||
|
{
|
||||||
|
// This function assumes that all tags for a single sector get added sequentially.
|
||||||
|
// Should there ever be some need for compatibility.txt to add tags to sectors which already have a tag this function needs to be changed to adjust the startForSector indices.
|
||||||
|
while (startForSector.Size() <= (unsigned int)sector)
|
||||||
|
{
|
||||||
|
startForSector.Push(-1);
|
||||||
|
}
|
||||||
|
if (startForSector[sector] == -1)
|
||||||
|
{
|
||||||
|
startForSector[sector] = allTags.Size();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// check if the key was already defined
|
||||||
|
for (unsigned i = startForSector[sector]; i < allTags.Size(); i++)
|
||||||
|
{
|
||||||
|
if (allTags[i].tag == tag)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FTagItem it = { sector, tag, -1 };
|
||||||
|
allTags.Push(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FTagManager::RemoveSectorTags(int sect)
|
||||||
|
{
|
||||||
|
int start = startForSector[sect];
|
||||||
|
if (start >= 0)
|
||||||
|
{
|
||||||
|
while (allTags[start].target == sect)
|
||||||
|
{
|
||||||
|
allTags[start].tag = allTags[start].target = -1;
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FTagManager::HashTags()
|
||||||
|
{
|
||||||
|
// add an end marker so we do not need to check for the array's size in the other functions.
|
||||||
|
static FTagItem it = { -1, -1, -1 };
|
||||||
|
allTags.Push(it);
|
||||||
|
|
||||||
|
// Initially make all slots empty.
|
||||||
|
memset(TagHashFirst, -1, sizeof(TagHashFirst));
|
||||||
|
|
||||||
|
// Proceed from last to first so that lower targets appear first
|
||||||
|
for (int i = allTags.Size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (allTags[i].target > 0) // only link valid entries
|
||||||
|
{
|
||||||
|
int hash = ((unsigned int)allTags[i].tag) % FTagManager::TAG_HASH_SIZE;
|
||||||
|
allTags[i].nexttag = TagHashFirst[hash];
|
||||||
|
TagHashFirst[hash] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool FTagManager::SectorHasTags(const sector_t *sector) const
|
||||||
|
{
|
||||||
|
int i = sectindex(sector);
|
||||||
|
return SectorHasTags(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int FTagManager::GetFirstSectorTag(const sector_t *sect) const
|
||||||
|
{
|
||||||
|
int i = sectindex(sect);
|
||||||
|
return SectorHasTags(i) ? allTags[startForSector[i]].tag : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool FTagManager::SectorHasTag(int i, int tag) const
|
||||||
|
{
|
||||||
|
if (SectorHasTags(i))
|
||||||
|
{
|
||||||
|
int ndx = startForSector[i];
|
||||||
|
while (allTags[ndx].target == i)
|
||||||
|
{
|
||||||
|
if (allTags[ndx].tag == tag) return true;
|
||||||
|
ndx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool FTagManager::SectorHasTag(const sector_t *sector, int tag) const
|
||||||
|
{
|
||||||
|
return SectorHasTag(sectindex(sector), tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
|
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
|
||||||
//
|
//
|
||||||
|
|
||||||
// Find the next sector with a specified tag.
|
// Find the next sector with a specified tag.
|
||||||
// Rewritten by Lee Killough to use chained hashing to improve speed
|
// Rewritten by Lee Killough to use chained hashing to improve speed
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
int FSectorTagIterator::Next()
|
int FSectorTagIterator::Next()
|
||||||
{
|
{
|
||||||
|
@ -53,27 +203,37 @@ int FSectorTagIterator::Next()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (start != -1 && sectors[start].tag != searchtag) start = sectors[start].nexttag;
|
while (start >= 0 && tagManager.allTags[start].tag != searchtag) start = tagManager.allTags[start].nexttag;
|
||||||
if (start == -1) return -1;
|
if (start == -1) return -1;
|
||||||
ret = start;
|
ret = start;
|
||||||
start = sectors[start].nexttag;
|
start = start = tagManager.allTags[start].nexttag;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// linear search for compatible stair building
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
int FSectorTagIterator::NextCompat(bool compat, int start)
|
int FSectorTagIterator::NextCompat(bool compat, int start)
|
||||||
{
|
{
|
||||||
if (!compat) return Next();
|
if (!compat) return Next();
|
||||||
|
|
||||||
for (int i = start + 1; i < numsectors; i++)
|
for (int i = start + 1; i < numsectors; i++)
|
||||||
{
|
{
|
||||||
if (sectors[i].HasTag(searchtag)) return i;
|
if (tagManager.SectorHasTag(i, searchtag)) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
// killough 4/16/98: Same thing, only for linedefs
|
// killough 4/16/98: Same thing, only for linedefs
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
int FLineIdIterator::Next()
|
int FLineIdIterator::Next()
|
||||||
{
|
{
|
||||||
|
|
57
src/p_tags.h
57
src/p_tags.h
|
@ -4,6 +4,59 @@
|
||||||
#include "r_defs.h"
|
#include "r_defs.h"
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
|
|
||||||
|
struct FTagItem
|
||||||
|
{
|
||||||
|
int target; // either sector or line
|
||||||
|
int tag;
|
||||||
|
int nexttag; // for hashing
|
||||||
|
};
|
||||||
|
|
||||||
|
class FSectorTagIterator;
|
||||||
|
|
||||||
|
class FTagManager
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TAG_HASH_SIZE = 256
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class FSectorTagIterator;
|
||||||
|
|
||||||
|
TArray<FTagItem> allTags;
|
||||||
|
TArray<FTagItem> allIDs;
|
||||||
|
TArray<int> startForSector;
|
||||||
|
TArray<int> startForLine;
|
||||||
|
int TagHashFirst[TAG_HASH_SIZE];
|
||||||
|
|
||||||
|
bool SectorHasTags(int sect) const
|
||||||
|
{
|
||||||
|
return sect >= 0 && sect < (int)startForSector.Size() && startForSector[sect] >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
allTags.Clear();
|
||||||
|
allIDs.Clear();
|
||||||
|
startForSector.Clear();
|
||||||
|
startForLine.Clear();
|
||||||
|
memset(TagHashFirst, -1, sizeof(TagHashFirst));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SectorHasTags(const sector_t *sector) const;
|
||||||
|
int GetFirstSectorTag(const sector_t *sect) const;
|
||||||
|
bool SectorHasTag(int sector, int tag) const;
|
||||||
|
bool SectorHasTag(const sector_t *sector, int tag) const;
|
||||||
|
|
||||||
|
bool LineHasID(int line, int id);
|
||||||
|
void HashTags();
|
||||||
|
void AddSectorTag(int sector, int tag);
|
||||||
|
void RemoveSectorTags(int sect);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FTagManager tagManager;
|
||||||
|
|
||||||
class FSectorTagIterator
|
class FSectorTagIterator
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -14,7 +67,7 @@ public:
|
||||||
FSectorTagIterator(int tag)
|
FSectorTagIterator(int tag)
|
||||||
{
|
{
|
||||||
searchtag = tag;
|
searchtag = tag;
|
||||||
start = sectors[(unsigned)tag % (unsigned)numsectors].firsttag;
|
start = tagManager.TagHashFirst[((unsigned int)tag) % FTagManager::TAG_HASH_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special constructor for actions that treat tag 0 as 'back of activation line'
|
// Special constructor for actions that treat tag 0 as 'back of activation line'
|
||||||
|
@ -28,7 +81,7 @@ public:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
searchtag = tag;
|
searchtag = tag;
|
||||||
start = sectors[(unsigned)tag % (unsigned)numsectors].firsttag;
|
start = tagManager.TagHashFirst[((unsigned int)tag) % FTagManager::TAG_HASH_SIZE];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,7 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while ( (searcher = iterator.Next ()) )
|
while ( (searcher = iterator.Next ()) )
|
||||||
{
|
{
|
||||||
if (tag == 0 || searcher->Sector->HasTag(tag))
|
if (tag == 0 || tagManager.SectorHasTag(searcher->Sector, tag))
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
{
|
{
|
||||||
searcher = iterator.Next ();
|
searcher = iterator.Next ();
|
||||||
if (tag == 0 || searcher->Sector->HasTag(tag))
|
if (tag == 0 || tagManager.SectorHasTag(searcher->Sector, tag))
|
||||||
{
|
{
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
|
#include "p_tags.h"
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -1269,6 +1270,7 @@ public:
|
||||||
int desaturation = -1;
|
int desaturation = -1;
|
||||||
int fplaneflags = 0, cplaneflags = 0;
|
int fplaneflags = 0, cplaneflags = 0;
|
||||||
double fp[4] = { 0 }, cp[4] = { 0 };
|
double fp[4] = { 0 }, cp[4] = { 0 };
|
||||||
|
FString tagstring;
|
||||||
|
|
||||||
memset(sec, 0, sizeof(*sec));
|
memset(sec, 0, sizeof(*sec));
|
||||||
sec->lightlevel = 160;
|
sec->lightlevel = 160;
|
||||||
|
@ -1332,7 +1334,7 @@ public:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case NAME_Id:
|
case NAME_Id:
|
||||||
sec->SetMainTag((short)CheckInt(key));
|
tagManager.AddSectorTag(index, CheckInt(key));
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1510,28 +1512,32 @@ public:
|
||||||
cp[3] = CheckFloat(key);
|
cp[3] = CheckFloat(key);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NAME_MoreIds:
|
||||||
|
// delay parsing of the tag string until parsing of the sector is complete
|
||||||
|
// This ensures that the ID is always the first tag in the list.
|
||||||
|
tagstring = CheckString(key);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if 0 // for later
|
|
||||||
if (namespace_bits & (Zd)) && !strnicmp(key.GetChars(), "Id", 2))
|
|
||||||
{
|
|
||||||
char *endp;
|
|
||||||
int num = strtol(key.GetChars(), &endp, 10);
|
|
||||||
if (num > 0 && *endp == NULL)
|
|
||||||
{
|
|
||||||
// only allow ID## with ## as a proper number
|
|
||||||
sec->SetTag((short)CheckInt(key), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5))
|
if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5))
|
||||||
{
|
{
|
||||||
AddUserKey(key, UDMF_Sector, index);
|
AddUserKey(key, UDMF_Sector, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tagstring.IsNotEmpty())
|
||||||
|
{
|
||||||
|
FScanner sc;
|
||||||
|
sc.OpenMem("tagstring", tagstring.GetChars(), tagstring.Len());
|
||||||
|
// scan the string as long as valid numbers can be found
|
||||||
|
while (sc.CheckNumber())
|
||||||
|
{
|
||||||
|
if (sc.Number != 0) tagManager.AddSectorTag(index, sc.Number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sec->secretsector = !!(sec->special&SECRET_MASK);
|
sec->secretsector = !!(sec->special&SECRET_MASK);
|
||||||
|
|
||||||
// Reset the planes to their defaults if not all of the plane equation's parameters were found.
|
// Reset the planes to their defaults if not all of the plane equation's parameters were found.
|
||||||
|
|
|
@ -262,7 +262,7 @@ static int WriteSECTORS (FILE *file)
|
||||||
uppercopy (ms.ceilingpic, GetTextureName (sectors[i].GetTexture(sector_t::ceiling)));
|
uppercopy (ms.ceilingpic, GetTextureName (sectors[i].GetTexture(sector_t::ceiling)));
|
||||||
ms.lightlevel = LittleShort((short)sectors[i].lightlevel);
|
ms.lightlevel = LittleShort((short)sectors[i].lightlevel);
|
||||||
ms.special = LittleShort(sectors[i].special);
|
ms.special = LittleShort(sectors[i].special);
|
||||||
ms.tag = LittleShort(sectors[i].GetMainTag());
|
ms.tag = LittleShort(tagManager.GetFirstSectorTag(§ors[i]));
|
||||||
fwrite (&ms, sizeof(ms), 1, file);
|
fwrite (&ms, sizeof(ms), 1, file);
|
||||||
}
|
}
|
||||||
return numsectors * sizeof(ms);
|
return numsectors * sizeof(ms);
|
||||||
|
|
|
@ -307,7 +307,7 @@ void P_TranslateTeleportThings ()
|
||||||
|
|
||||||
while ( (dest = iterator.Next()) )
|
while ( (dest = iterator.Next()) )
|
||||||
{
|
{
|
||||||
if (!dest->Sector->HasTags())
|
if (!tagManager.SectorHasTags(dest->Sector))
|
||||||
{
|
{
|
||||||
dest->tid = 1;
|
dest->tid = 1;
|
||||||
dest->AddToHash ();
|
dest->AddToHash ();
|
||||||
|
|
|
@ -633,12 +633,6 @@ struct sector_t
|
||||||
return pos == floor? floorplane:ceilingplane;
|
return pos == floor? floorplane:ceilingplane;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasTag(int checktag) const;
|
|
||||||
bool HasTags() const;
|
|
||||||
void SetMainTag(int tagnum);
|
|
||||||
int GetMainTag() const;
|
|
||||||
void ClearTags();
|
|
||||||
static void HashTags();
|
|
||||||
|
|
||||||
bool PlaneMoving(int pos);
|
bool PlaneMoving(int pos);
|
||||||
|
|
||||||
|
@ -657,12 +651,9 @@ struct sector_t
|
||||||
TObjPtr<AActor> SoundTarget;
|
TObjPtr<AActor> SoundTarget;
|
||||||
|
|
||||||
short special;
|
short special;
|
||||||
short tag;
|
|
||||||
short lightlevel;
|
short lightlevel;
|
||||||
short seqType; // this sector's sound sequence
|
short seqType; // this sector's sound sequence
|
||||||
|
|
||||||
int nexttag,firsttag; // killough 1/30/98: improves searches for tags.
|
|
||||||
|
|
||||||
int sky;
|
int sky;
|
||||||
FNameNoInit SeqName; // Sound sequence name. Setting seqType non-negative will override this.
|
FNameNoInit SeqName; // Sound sequence name. Setting seqType non-negative will override this.
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ const char *GetVersionString();
|
||||||
|
|
||||||
// Use 4500 as the base git save version, since it's higher than the
|
// Use 4500 as the base git save version, since it's higher than the
|
||||||
// SVN revision ever got.
|
// SVN revision ever got.
|
||||||
#define SAVEVER 4522
|
#define SAVEVER 4523
|
||||||
|
|
||||||
#define SAVEVERSTRINGIFY2(x) #x
|
#define SAVEVERSTRINGIFY2(x) #x
|
||||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||||
|
|
Loading…
Reference in a new issue