diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f9e733ce6..a627e0fdc9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1079,6 +1079,7 @@ set (PCH_SOURCES maploader/slopes.cpp maploader/glnodes.cpp maploader/udmf.cpp + maploader/polyobjects.cpp menu/joystickmenu.cpp menu/loadsavemenu.cpp menu/menu.cpp diff --git a/src/g_levellocals.h b/src/g_levellocals.h index f3d594e5a2..40d1fc6321 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -83,6 +83,7 @@ struct FLevelData TMap healthGroups; FBlockmap blockmap; + TArray PolyBlockMap; // These are copies of the loaded map data that get used by the savegame code to skip unaltered fields // Without such a mechanism the savegame format would become too slow and large because more than 80-90% are normally still unaltered. diff --git a/src/maploader/polyobjects.cpp b/src/maploader/polyobjects.cpp new file mode 100644 index 0000000000..2bb54a969d --- /dev/null +++ b/src/maploader/polyobjects.cpp @@ -0,0 +1,415 @@ +//----------------------------------------------------------------------------- +// +// Copyright 1994-1996 Raven Software +// Copyright 1999-2016 Randy Heit +// Copyright 2002-2018 Christoph Oelckers +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//----------------------------------------------------------------------------- +// + +// HEADER FILES ------------------------------------------------------------ + +#include "doomdef.h" +#include "p_local.h" +#include "m_bbox.h" +#include "a_sharedglobal.h" +#include "p_3dmidtex.h" +#include "p_lnspec.h" +#include "po_man.h" +#include "p_setup.h" +#include "p_blockmap.h" +#include "p_maputl.h" +#include "r_utility.h" +#include "g_levellocals.h" +#include "actorinlines.h" +#include "v_text.h" + +#include "maploader/maploader.h" + +//========================================================================== +// +// InitBlockMap +// +//========================================================================== + +void MapLoader::InitPolyBlockMap () +{ + int bmapwidth = Level->blockmap.bmapwidth; + int bmapheight = Level->blockmap.bmapheight; + + Level->PolyBlockMap.Resize(bmapwidth*bmapheight); + memset (Level->PolyBlockMap.Data(), 0, bmapwidth*bmapheight*sizeof(polyblock_t *)); + + for(auto &poly : Level->Polyobjects) + { + poly.LinkPolyobj(); + } +} + +//========================================================================== +// +// InitSideLists [RH] +// +// Group sides by vertex and collect side that are known to belong to a +// polyobject so that they can be initialized fast. +//========================================================================== + +void MapLoader::InitSideLists () +{ + auto &sides = Level->sides; + for (unsigned i = 0; i < sides.Size(); ++i) + { + if (sides[i].linedef != NULL && + (sides[i].linedef->special == Polyobj_StartLine || + sides[i].linedef->special == Polyobj_ExplicitLine)) + { + KnownPolySides.Push (i); + } + } +} + +//========================================================================== +// +// AddPolyVert +// +// Helper function for IterFindPolySides() +// +//========================================================================== + +static void AddPolyVert(TArray &vnum, uint32_t vert) +{ + for (unsigned int i = vnum.Size() - 1; i-- != 0; ) + { + if (vnum[i] == vert) + { // Already in the set. No need to add it. + return; + } + } + vnum.Push(vert); +} + +//========================================================================== +// +// IterFindPolySides +// +// Beginning with the first vertex of the starting side, for each vertex +// in vnum, add all the sides that use it as a first vertex to the polyobj, +// and add all their second vertices to vnum. This continues until there +// are no new vertices in vnum. +// +//========================================================================== + +void MapLoader::IterFindPolySides (FPolyObj *po, side_t *side) +{ + static TArray vnum; + unsigned int vnumat; + + assert(sidetemp != NULL); + + vnum.Clear(); + vnum.Push(uint32_t(side->V1()->Index())); + vnumat = 0; + + while (vnum.Size() != vnumat) + { + uint32_t sidenum = sidetemp[vnum[vnumat++]].b.first; + while (sidenum != NO_SIDE) + { + po->Sidedefs.Push(&Level->sides[sidenum]); + AddPolyVert(vnum, uint32_t(Level->sides[sidenum].V2()->Index())); + sidenum = sidetemp[sidenum].b.next; + } + } +} + + +//========================================================================== +// +// SpawnPolyobj +// +//========================================================================== + +static int posicmp(const void *a, const void *b) +{ + return (*(const side_t **)a)->linedef->args[1] - (*(const side_t **)b)->linedef->args[1]; +} + +void MapLoader::SpawnPolyobj (int index, int tag, int type) +{ + unsigned int ii; + int i; + FPolyObj *po = &Level->Polyobjects[index]; + + for (ii = 0; ii < KnownPolySides.Size(); ++ii) + { + i = KnownPolySides[ii]; + if (i < 0) + { + continue; + } + po->bBlocked = false; + po->bHasPortals = 0; + + side_t *sd = &Level->sides[i]; + + if (sd->linedef->special == Polyobj_StartLine && + sd->linedef->args[0] == tag) + { + if (po->Sidedefs.Size() > 0) + { + Printf (TEXTCOLOR_RED "SpawnPolyobj: Polyobj %d already spawned.\n", tag); + return; + } + else + { + sd->linedef->special = 0; + sd->linedef->args[0] = 0; + IterFindPolySides(&Level->Polyobjects[index], sd); + po->MirrorNum = sd->linedef->args[1]; + po->crush = (type != SMT_PolySpawn) ? 3 : 0; + po->bHurtOnTouch = (type == SMT_PolySpawnHurt); + po->tag = tag; + po->seqType = sd->linedef->args[2]; + if (po->seqType < 0 || po->seqType > 63) + { + po->seqType = 0; + } + } + break; + } + } + if (po->Sidedefs.Size() == 0) + { + // didn't find a polyobj through PO_LINE_START + TArray polySideList; + unsigned int psIndexOld; + psIndexOld = po->Sidedefs.Size(); + + for (ii = 0; ii < KnownPolySides.Size(); ++ii) + { + i = KnownPolySides[ii]; + + if (i >= 0 && + Level->sides[i].linedef->special == Polyobj_ExplicitLine && + Level->sides[i].linedef->args[0] == tag) + { + if (!Level->sides[i].linedef->args[1]) + { + Printf(TEXTCOLOR_RED "SpawnPolyobj: Explicit line missing order number in poly %d, linedef %d.\n", tag, Level->sides[i].linedef->Index()); + return; + } + else + { + po->Sidedefs.Push(&Level->sides[i]); + } + } + } + qsort(&po->Sidedefs[0], po->Sidedefs.Size(), sizeof(po->Sidedefs[0]), posicmp); + if (po->Sidedefs.Size() > 0) + { + po->crush = (type != SMT_PolySpawn) ? 3 : 0; + po->bHurtOnTouch = (type == SMT_PolySpawnHurt); + po->tag = tag; + po->seqType = po->Sidedefs[0]->linedef->args[3]; + po->MirrorNum = po->Sidedefs[0]->linedef->args[2]; + } + else + { + Printf(TEXTCOLOR_RED "SpawnPolyobj: Poly %d does not exist\n", tag); + return; + } + } + + validcount++; + for(unsigned int i=0; iSidedefs.Size(); i++) + { + line_t *l = po->Sidedefs[i]->linedef; + + if (l->validcount != validcount) + { + FLinePortal *port = l->getPortal(); + if (port && (port->mDefFlags & PORTF_PASSABLE)) + { + int type = port->mType == PORTT_LINKED ? 2 : 1; + if (po->bHasPortals < type) po->bHasPortals = (uint8_t)type; + } + l->validcount = validcount; + po->Linedefs.Push(l); + + vertex_t *v = l->v1; + int j; + for(j = po->Vertices.Size() - 1; j >= 0; j--) + { + if (po->Vertices[j] == v) break; + } + if (j < 0) po->Vertices.Push(v); + + v = l->v2; + for(j = po->Vertices.Size() - 1; j >= 0; j--) + { + if (po->Vertices[j] == v) break; + } + if (j < 0) po->Vertices.Push(v); + + } + } + po->Sidedefs.ShrinkToFit(); + po->Linedefs.ShrinkToFit(); + po->Vertices.ShrinkToFit(); +} + +//========================================================================== +// +// TranslateToStartSpot +// +//========================================================================== + +void MapLoader::TranslateToStartSpot (int tag, const DVector2 &origin) +{ + FPolyObj *po; + DVector2 delta; + + po = PO_GetPolyobj(tag); + if (po == nullptr) + { // didn't match the tag with a polyobj tag + Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); + return; + } + if (po->Sidedefs.Size() == 0) + { + Printf(TEXTCOLOR_RED "TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", tag); + return; + } + po->OriginalPts.Resize(po->Sidedefs.Size()); + po->PrevPts.Resize(po->Sidedefs.Size()); + delta = origin - po->StartSpot.pos; + + for (unsigned i = 0; i < po->Sidedefs.Size(); i++) + { + po->Sidedefs[i]->Flags |= WALLF_POLYOBJ; + } + for (unsigned i = 0; i < po->Linedefs.Size(); i++) + { + po->Linedefs[i]->bbox[BOXTOP] -= delta.Y; + po->Linedefs[i]->bbox[BOXBOTTOM] -= delta.Y; + po->Linedefs[i]->bbox[BOXLEFT] -= delta.X; + po->Linedefs[i]->bbox[BOXRIGHT] -= delta.X; + } + for (unsigned i = 0; i < po->Vertices.Size(); i++) + { + po->Vertices[i]->set(po->Vertices[i]->fX() - delta.X, po->Vertices[i]->fY() - delta.Y); + po->OriginalPts[i].pos = po->Vertices[i]->fPos() - po->StartSpot.pos; + } + po->CalcCenter(); + // For compatibility purposes + po->CenterSubsector = R_PointInSubsector(po->CenterSpot.pos); +} + +//========================================================================== +// +// PO_Init +// +//========================================================================== + +void MapLoader::PO_Init (void) +{ + int NumPolyobjs = 0; + TArray polythings; + for (auto &mthing : MapThingsConverted) + { + if (mthing.EdNum == 0 || mthing.EdNum == -1) continue; + + FDoomEdEntry *mentry = mthing.info; + switch (mentry->Special) + { + case SMT_PolyAnchor: + case SMT_PolySpawn: + case SMT_PolySpawnCrush: + case SMT_PolySpawnHurt: + polythings.Push(&mthing); + if (mentry->Special != SMT_PolyAnchor) + NumPolyobjs++; + } + } + + int polyIndex; + + // [RH] Make this faster + InitSideLists (); + + Level->Polyobjects.Resize(NumPolyobjs); + + polyIndex = 0; // index polyobj number + // Find the startSpot points, and spawn each polyobj + for (int i=polythings.Size()-1; i >= 0; i--) + { + // 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch + int type = polythings[i]->info->Special; + if (type >= SMT_PolySpawn && type <= SMT_PolySpawnHurt) + { + // Polyobj StartSpot Pt. + Level->Polyobjects[polyIndex].StartSpot.pos = polythings[i]->pos; + SpawnPolyobj(polyIndex, polythings[i]->angle, type); + polyIndex++; + } + } + for (int i = polythings.Size() - 1; i >= 0; i--) + { + int type = polythings[i]->info->Special; + if (type == SMT_PolyAnchor) + { + // Polyobj Anchor Pt. + TranslateToStartSpot (polythings[i]->angle, polythings[i]->pos); + } + } + + // check for a startspot without an anchor point + for (auto &poly : Level->Polyobjects) + { + if (poly.OriginalPts.Size() == 0) + { + Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", poly.tag); + } + } + InitPolyBlockMap(); + + // [RH] Don't need the side lists anymore + KnownPolySides.Reset(); + + // mark all subsectors which have a seg belonging to a polyobj + // These ones should not be rendered on the textured automap. + for (auto &ss : Level->subsectors) + { + for(uint32_t j=0;jFlags & WALLF_POLYOBJ) + { + ss.flags |= SSECF_POLYORG; + break; + } + } + } + // clear all polyobj specials so that they do not obstruct using other lines. + for (auto &line : Level->lines) + { + if (line.special == Polyobj_ExplicitLine || line.special == Polyobj_StartLine) + { + line.special = 0; + } + } +} + diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 9cd5352b8f..64f904a7ca 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -581,7 +581,6 @@ void AActor::SetOrigin(double x, double y, double z, bool moving) // FBlockLinesIterator // //=========================================================================== -extern polyblock_t **PolyBlockMap; FBlockLinesIterator::FBlockLinesIterator(int _minx, int _miny, int _maxx, int _maxy, bool keepvalidcount) { @@ -621,7 +620,7 @@ void FBlockLinesIterator::StartBlock(int x, int y) if (level.blockmap.isValidBlock(x, y)) { int offset = y*level.blockmap.bmapwidth + x; - polyLink = PolyBlockMap? PolyBlockMap[offset] : NULL; + polyLink = level.PolyBlockMap.Size() > offset? level.PolyBlockMap[offset] : nullptr; polyIndex = 0; list = level.blockmap.GetLines(x, y); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 1dcc4eb664..85e8198139 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -80,8 +80,6 @@ extern unsigned int R_OldBlend; static void P_Shutdown (); -extern polyblock_t **PolyBlockMap; - //=========================================================================== // // P_PrecacheLevel @@ -279,21 +277,17 @@ void P_FreeLevelData () level.blockmap.Clear(); level.Polyobjects.Clear(); - if (PolyBlockMap != nullptr) + for(auto &pb : level.PolyBlockMap) { - for (int i = level.blockmap.bmapwidth*level.blockmap.bmapheight-1; i >= 0; --i) + polyblock_t *link = pb; + while (link != nullptr) { - polyblock_t *link = PolyBlockMap[i]; - while (link != nullptr) - { - polyblock_t *next = link->next; - delete link; - link = next; - } + polyblock_t *next = link->next; + delete link; + link = next; } - delete[] PolyBlockMap; - PolyBlockMap = nullptr; } + level.PolyBlockMap.Reset(); level.deathmatchstarts.Clear(); level.AllPlayerStarts.Clear(); diff --git a/src/p_sight.cpp b/src/p_sight.cpp index 5f15e844bb..ba4c97719e 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -476,7 +476,6 @@ int SightCheck::P_SightBlockLinesIterator (int x, int y) polyblock_t *polyLink; unsigned int i; - extern polyblock_t **PolyBlockMap; offset = y*level.blockmap.bmapwidth+x; @@ -484,7 +483,7 @@ int SightCheck::P_SightBlockLinesIterator (int x, int y) // (We still try to delay activating this for as long as possible.) portalfound = portalfound || level.PortalBlockmap(x, y).containsLinkedPortals; - polyLink = PolyBlockMap[offset]; + polyLink = level.PolyBlockMap[offset]; portalfound |= (polyLink && level.PortalBlockmap.hasLinkedPolyPortals); while (polyLink) { diff --git a/src/po_man.cpp b/src/po_man.cpp index e936324e40..9643ee6e9e 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -2,7 +2,7 @@ // // Copyright 1994-1996 Raven Software // Copyright 1999-2016 Randy Heit -// Copyright 2002-2016 Christoph Oelckers +// Copyright 2002-2018 Christoph Oelckers // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -40,12 +40,6 @@ #include "actorinlines.h" #include "v_text.h" -#include "maploader/maploader.h" - -// MACROS ------------------------------------------------------------------ - -#define PO_MAXPOLYSEGS 64 - // TYPES ------------------------------------------------------------------- class DRotatePoly : public DPolyAction @@ -138,8 +132,6 @@ static void ReleaseAllPolyNodes(); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -polyblock_t **PolyBlockMap; - // PRIVATE DATA DEFINITIONS ------------------------------------------------ static FPolyNode *FreePolyNodes; @@ -1065,7 +1057,7 @@ void FPolyObj::UnLinkPolyobj () { if(i >= 0 && i < level.blockmap.bmapwidth && j >= 0 && j < level.blockmap.bmapheight) { - link = PolyBlockMap[index+i]; + link = level.PolyBlockMap[index+i]; while(link != NULL && link->polyobj != this) { link = link->next; @@ -1249,7 +1241,7 @@ void FPolyObj::LinkPolyobj () { if(i >= 0 && i < bmapwidth && j >= 0 && j < bmapheight*bmapwidth) { - link = &PolyBlockMap[j+i]; + link = &level.PolyBlockMap[j+i]; if(!(*link)) { // Create a new link at the current block cell *link = new polyblock_t; @@ -1384,380 +1376,6 @@ void FPolyObj::ClosestPoint(const DVector2 &fpos, DVector2 &out, side_t **side) } } -//========================================================================== -// -// InitBlockMap -// -//========================================================================== - -void MapLoader::InitPolyBlockMap () -{ - int bmapwidth = Level->blockmap.bmapwidth; - int bmapheight = Level->blockmap.bmapheight; - - PolyBlockMap = new polyblock_t *[bmapwidth*bmapheight]; - memset (PolyBlockMap, 0, bmapwidth*bmapheight*sizeof(polyblock_t *)); - - for(auto &poly : Level->Polyobjects) - { - poly.LinkPolyobj(); - } -} - -//========================================================================== -// -// InitSideLists [RH] -// -// Group sides by vertex and collect side that are known to belong to a -// polyobject so that they can be initialized fast. -//========================================================================== - -void MapLoader::InitSideLists () -{ - auto &sides = Level->sides; - for (unsigned i = 0; i < sides.Size(); ++i) - { - if (sides[i].linedef != NULL && - (sides[i].linedef->special == Polyobj_StartLine || - sides[i].linedef->special == Polyobj_ExplicitLine)) - { - KnownPolySides.Push (i); - } - } -} - -//========================================================================== -// -// AddPolyVert -// -// Helper function for IterFindPolySides() -// -//========================================================================== - -static void AddPolyVert(TArray &vnum, uint32_t vert) -{ - for (unsigned int i = vnum.Size() - 1; i-- != 0; ) - { - if (vnum[i] == vert) - { // Already in the set. No need to add it. - return; - } - } - vnum.Push(vert); -} - -//========================================================================== -// -// IterFindPolySides -// -// Beginning with the first vertex of the starting side, for each vertex -// in vnum, add all the sides that use it as a first vertex to the polyobj, -// and add all their second vertices to vnum. This continues until there -// are no new vertices in vnum. -// -//========================================================================== - -void MapLoader::IterFindPolySides (FPolyObj *po, side_t *side) -{ - static TArray vnum; - unsigned int vnumat; - - assert(sidetemp != NULL); - - vnum.Clear(); - vnum.Push(uint32_t(side->V1()->Index())); - vnumat = 0; - - while (vnum.Size() != vnumat) - { - uint32_t sidenum = sidetemp[vnum[vnumat++]].b.first; - while (sidenum != NO_SIDE) - { - po->Sidedefs.Push(&Level->sides[sidenum]); - AddPolyVert(vnum, uint32_t(Level->sides[sidenum].V2()->Index())); - sidenum = sidetemp[sidenum].b.next; - } - } -} - - -//========================================================================== -// -// SpawnPolyobj -// -//========================================================================== - -static int posicmp(const void *a, const void *b) -{ - return (*(const side_t **)a)->linedef->args[1] - (*(const side_t **)b)->linedef->args[1]; -} - -void MapLoader::SpawnPolyobj (int index, int tag, int type) -{ - unsigned int ii; - int i; - FPolyObj *po = &Level->Polyobjects[index]; - - for (ii = 0; ii < KnownPolySides.Size(); ++ii) - { - i = KnownPolySides[ii]; - if (i < 0) - { - continue; - } - po->bBlocked = false; - po->bHasPortals = 0; - - side_t *sd = &Level->sides[i]; - - if (sd->linedef->special == Polyobj_StartLine && - sd->linedef->args[0] == tag) - { - if (po->Sidedefs.Size() > 0) - { - Printf (TEXTCOLOR_RED "SpawnPolyobj: Polyobj %d already spawned.\n", tag); - return; - } - else - { - sd->linedef->special = 0; - sd->linedef->args[0] = 0; - IterFindPolySides(&Level->Polyobjects[index], sd); - po->MirrorNum = sd->linedef->args[1]; - po->crush = (type != SMT_PolySpawn) ? 3 : 0; - po->bHurtOnTouch = (type == SMT_PolySpawnHurt); - po->tag = tag; - po->seqType = sd->linedef->args[2]; - if (po->seqType < 0 || po->seqType > 63) - { - po->seqType = 0; - } - } - break; - } - } - if (po->Sidedefs.Size() == 0) - { - // didn't find a polyobj through PO_LINE_START - TArray polySideList; - unsigned int psIndexOld; - psIndexOld = po->Sidedefs.Size(); - - for (ii = 0; ii < KnownPolySides.Size(); ++ii) - { - i = KnownPolySides[ii]; - - if (i >= 0 && - Level->sides[i].linedef->special == Polyobj_ExplicitLine && - Level->sides[i].linedef->args[0] == tag) - { - if (!Level->sides[i].linedef->args[1]) - { - Printf(TEXTCOLOR_RED "SpawnPolyobj: Explicit line missing order number in poly %d, linedef %d.\n", tag, Level->sides[i].linedef->Index()); - return; - } - else - { - po->Sidedefs.Push(&Level->sides[i]); - } - } - } - qsort(&po->Sidedefs[0], po->Sidedefs.Size(), sizeof(po->Sidedefs[0]), posicmp); - if (po->Sidedefs.Size() > 0) - { - po->crush = (type != SMT_PolySpawn) ? 3 : 0; - po->bHurtOnTouch = (type == SMT_PolySpawnHurt); - po->tag = tag; - po->seqType = po->Sidedefs[0]->linedef->args[3]; - po->MirrorNum = po->Sidedefs[0]->linedef->args[2]; - } - else - { - Printf(TEXTCOLOR_RED "SpawnPolyobj: Poly %d does not exist\n", tag); - return; - } - } - - validcount++; - for(unsigned int i=0; iSidedefs.Size(); i++) - { - line_t *l = po->Sidedefs[i]->linedef; - - if (l->validcount != validcount) - { - FLinePortal *port = l->getPortal(); - if (port && (port->mDefFlags & PORTF_PASSABLE)) - { - int type = port->mType == PORTT_LINKED ? 2 : 1; - if (po->bHasPortals < type) po->bHasPortals = (uint8_t)type; - } - l->validcount = validcount; - po->Linedefs.Push(l); - - vertex_t *v = l->v1; - int j; - for(j = po->Vertices.Size() - 1; j >= 0; j--) - { - if (po->Vertices[j] == v) break; - } - if (j < 0) po->Vertices.Push(v); - - v = l->v2; - for(j = po->Vertices.Size() - 1; j >= 0; j--) - { - if (po->Vertices[j] == v) break; - } - if (j < 0) po->Vertices.Push(v); - - } - } - po->Sidedefs.ShrinkToFit(); - po->Linedefs.ShrinkToFit(); - po->Vertices.ShrinkToFit(); -} - -//========================================================================== -// -// TranslateToStartSpot -// -//========================================================================== - -void MapLoader::TranslateToStartSpot (int tag, const DVector2 &origin) -{ - FPolyObj *po; - DVector2 delta; - - po = PO_GetPolyobj(tag); - if (po == nullptr) - { // didn't match the tag with a polyobj tag - Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); - return; - } - if (po->Sidedefs.Size() == 0) - { - Printf(TEXTCOLOR_RED "TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", tag); - return; - } - po->OriginalPts.Resize(po->Sidedefs.Size()); - po->PrevPts.Resize(po->Sidedefs.Size()); - delta = origin - po->StartSpot.pos; - - for (unsigned i = 0; i < po->Sidedefs.Size(); i++) - { - po->Sidedefs[i]->Flags |= WALLF_POLYOBJ; - } - for (unsigned i = 0; i < po->Linedefs.Size(); i++) - { - po->Linedefs[i]->bbox[BOXTOP] -= delta.Y; - po->Linedefs[i]->bbox[BOXBOTTOM] -= delta.Y; - po->Linedefs[i]->bbox[BOXLEFT] -= delta.X; - po->Linedefs[i]->bbox[BOXRIGHT] -= delta.X; - } - for (unsigned i = 0; i < po->Vertices.Size(); i++) - { - po->Vertices[i]->set(po->Vertices[i]->fX() - delta.X, po->Vertices[i]->fY() - delta.Y); - po->OriginalPts[i].pos = po->Vertices[i]->fPos() - po->StartSpot.pos; - } - po->CalcCenter(); - // For compatibility purposes - po->CenterSubsector = R_PointInSubsector(po->CenterSpot.pos); -} - -//========================================================================== -// -// PO_Init -// -//========================================================================== - -void MapLoader::PO_Init (void) -{ - int NumPolyobjs = 0; - TArray polythings; - for (auto &mthing : MapThingsConverted) - { - if (mthing.EdNum == 0 || mthing.EdNum == -1) continue; - - FDoomEdEntry *mentry = mthing.info; - switch (mentry->Special) - { - case SMT_PolyAnchor: - case SMT_PolySpawn: - case SMT_PolySpawnCrush: - case SMT_PolySpawnHurt: - polythings.Push(&mthing); - if (mentry->Special != SMT_PolyAnchor) - NumPolyobjs++; - } - } - - int polyIndex; - - // [RH] Make this faster - InitSideLists (); - - Level->Polyobjects.Resize(NumPolyobjs); - - polyIndex = 0; // index polyobj number - // Find the startSpot points, and spawn each polyobj - for (int i=polythings.Size()-1; i >= 0; i--) - { - // 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch - int type = polythings[i]->info->Special; - if (type >= SMT_PolySpawn && type <= SMT_PolySpawnHurt) - { - // Polyobj StartSpot Pt. - Level->Polyobjects[polyIndex].StartSpot.pos = polythings[i]->pos; - SpawnPolyobj(polyIndex, polythings[i]->angle, type); - polyIndex++; - } - } - for (int i = polythings.Size() - 1; i >= 0; i--) - { - int type = polythings[i]->info->Special; - if (type == SMT_PolyAnchor) - { - // Polyobj Anchor Pt. - TranslateToStartSpot (polythings[i]->angle, polythings[i]->pos); - } - } - - // check for a startspot without an anchor point - for (auto &poly : Level->Polyobjects) - { - if (poly.OriginalPts.Size() == 0) - { - Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", poly.tag); - } - } - InitPolyBlockMap(); - - // [RH] Don't need the side lists anymore - KnownPolySides.Reset(); - - // mark all subsectors which have a seg belonging to a polyobj - // These ones should not be rendered on the textured automap. - for (auto &ss : Level->subsectors) - { - for(uint32_t j=0;jFlags & WALLF_POLYOBJ) - { - ss.flags |= SSECF_POLYORG; - break; - } - } - } - // clear all polyobj specials so that they do not obstruct using other lines. - for (auto &line : Level->lines) - { - if (line.special == Polyobj_ExplicitLine || line.special == Polyobj_StartLine) - { - line.special = 0; - } - } -} - //========================================================================== // // PO_Busy