From ec888c097c194dfbc1a4ba5383190a80594fd8bd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 3 Dec 2021 22:19:28 +0100 Subject: [PATCH] - Blood: separated actor spawning from map loading. --- source/games/blood/src/blood.cpp | 86 ++++++++++++++++++++++++----- source/games/blood/src/bloodactor.h | 1 - source/games/blood/src/db.cpp | 82 +++++---------------------- source/games/blood/src/db.h | 8 ++- 4 files changed, 91 insertions(+), 86 deletions(-) diff --git a/source/games/blood/src/blood.cpp b/source/games/blood/src/blood.cpp index 46d28019d..8026080e1 100644 --- a/source/games/blood/src/blood.cpp +++ b/source/games/blood/src/blood.cpp @@ -79,6 +79,71 @@ void EndLevel(void) seqKillAll(); } +TArray SpawnActors(SpawnSpriteDef& sprites) +{ + TArray spawns(sprites.sprites.Size(), true); + initspritelists(); + for (unsigned i = 0; i < sprites.sprites.Size(); i++) + { + RemoveSpriteStat(i); + auto actor = &bloodActors[i]; + spawns[i] = actor; + actor->Clear(); + actor->s() = sprites.sprites[i]; + if (sprites.sprites[i].extra > 0) + { + actor->addX(); + actor->x() = sprites.xspr[i]; + } + + InsertSpriteSect(i, actor->s().sectnum); + InsertSpriteStat(i, actor->s().statnum); + } + Numsprites = spawns.Size(); + return spawns; +} + +void PropagateMarkerReferences(void) +{ + BloodStatIterator it(kStatMarker); + while (auto actor = it.Next()) + { + switch (actor->s().type) + { + case kMarkerOff: + case kMarkerAxis: + case kMarkerWarpDest: + { + int nOwner = actor->s().owner; + if (nOwner >= 0 && nOwner < numsectors) + { + if (sector[nOwner].hasX()) + { + sector[nOwner].xs().marker0 = actor; + continue; + } + } + } + break; + case kMarkerOn: + { + int nOwner = actor->s().owner; + if (nOwner >= 0 && nOwner < numsectors) + { + if (sector[nOwner].hasX()) + { + sector[nOwner].xs().marker1 = actor; + continue; + } + } + } + break; + } + + DeleteSprite(actor); + } +} + void StartLevel(MapRecord* level, bool newgame) { if (!level) return; @@ -111,7 +176,8 @@ void StartLevel(MapRecord* level, bool newgame) } } //drawLoadingScreen(); - dbLoadMap(currentLevel->fileName, (int*)&startpos.x, (int*)&startpos.y, (int*)&startpos.z, &startang, &startsector, nullptr); + SpawnSpriteDef sprites; + dbLoadMap(currentLevel->fileName, (int*)&startpos.x, (int*)&startpos.y, (int*)&startpos.z, &startang, &startsector, nullptr, sprites); SECRET_SetMapName(currentLevel->DisplayName(), currentLevel->name); STAT_NewLevel(currentLevel->fileName); wsrand(dbReadMapCRC(currentLevel->LabelName())); @@ -119,23 +185,13 @@ void StartLevel(MapRecord* level, bool newgame) gSecretMgr.Clear(); automapping = 1; - // Here is where later the actors must be spawned. - - // get a sorted list of all actors as we need to run some init code in spawn order. (iterating bloodActors would actually do, but that won't last forever) - TArray actorlist; - BloodSpriteIterator sit; - while (auto act = sit.Next()) - { - actorlist.Push(act); - } - std::sort(actorlist.begin(), actorlist.end(), [](DBloodActor* a, DBloodActor* b) { return a->GetIndex() < b->GetIndex(); }); - - + auto actorlist = SpawnActors(sprites); + PropagateMarkerReferences(); int modernTypesErased = 0; - for(unsigned i = 0; i < actorlist.Size(); i++) + for (auto actor : actorlist) { - auto actor = actorlist[i]; + spritetype* pSprite = &actor->s(); if (actor->exists() && actor->hasX()) { diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index 7c84e427b..5ae0c6c16 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -171,7 +171,6 @@ extern HitInfo gHitInfo; using BloodStatIterator = TStatIterator; using BloodSectIterator = TSectIterator; using BloodSpriteIterator = TSpriteIterator; -using BloodLinearSpriteIterator = TLinearSpriteIterator; inline void GetActorExtents(DBloodActor* actor, int* top, int* bottom) { diff --git a/source/games/blood/src/db.cpp b/source/games/blood/src/db.cpp index 6b2c9f58e..42c80a360 100644 --- a/source/games/blood/src/db.cpp +++ b/source/games/blood/src/db.cpp @@ -244,47 +244,6 @@ void dbInit(void) } } -void PropagateMarkerReferences(void) -{ - BloodStatIterator it(kStatMarker); - while (auto actor = it.Next()) - { - switch (actor->s().type) - { - case kMarkerOff: - case kMarkerAxis: - case kMarkerWarpDest: - { - int nOwner = actor->s().owner; - if (nOwner >= 0 && nOwner < numsectors) - { - if (sector[nOwner].hasX()) - { - sector[nOwner].xs().marker0 = actor; - continue; - } - } - } - break; - case kMarkerOn: - { - int nOwner = actor->s().owner; - if (nOwner >= 0 && nOwner < numsectors) - { - if (sector[nOwner].hasX()) - { - sector[nOwner].xs().marker1 = actor; - continue; - } - } - } - break; - } - - DeleteSprite(actor); - } -} - bool drawtile2048, encrypted; MAPHEADER2 byte_19AE44; @@ -384,8 +343,7 @@ struct walltypedisk #pragma pack(pop) - -void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sectortype** pSector, unsigned int* pCRC) +void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sectortype** pSector, unsigned int* pCRC, SpawnSpriteDef& sprites) { int16_t tpskyoff[256]; ClearAutomap(); @@ -728,21 +686,19 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect } } - initspritelists(); leveltimer = mapHeader.numsprites; + sprites.sprites.Resize(mapHeader.numsprites); + sprites.xspr.Resize(mapHeader.numsprites); for (int i = 0; i < mapHeader.numsprites; i++) { - RemoveSpriteStat(i); spritetypedisk load; - auto actor = &bloodActors[i]; - actor->Clear(); - spritetype* pSprite = &actor->s(); fr.Read(&load, sizeof(spritetypedisk)); // load into an intermediate buffer so that spritetype is no longer bound by file formats. if (encrypted) // What were these people thinking? :( { dbCrypt((char*)&load, sizeof(spritetypedisk), (gMapRev * sizeof(spritetypedisk)) | 0x7474614d); } - + auto pSprite = &sprites.sprites[i]; + pSprite->clear(); pSprite->x = LittleLong(load.x); pSprite->y = LittleLong(load.y); pSprite->z = LittleLong(load.z); @@ -770,14 +726,11 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect pSprite->time = i; ValidateSprite(*pSprite); - InsertSpriteSect(i, pSprite->sectnum); - InsertSpriteStat(i, pSprite->statnum); - Numsprites++; if (pSprite->extra > 0) { char pBuffer[nXSpriteSize]; - actor->addX(); - XSPRITE* pXSprite = &actor->x(); + XSPRITE* pXSprite = &sprites.xspr[i]; + *pXSprite = {}; int nCount; if (!encrypted) { @@ -863,10 +816,6 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect gModernMap = true; #endif } - if ((sprite[i].cstat & 0x30) == 0x30) - { - sprite[i].cstat &= ~0x30; - } } unsigned int nCRC = fr.ReadUInt32(); @@ -874,7 +823,7 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect auto buffer = fr.Read(); uint8_t md4[16]; md4once(buffer.Data(), buffer.Size(), md4); - G_LoadMapHack(mapname, md4, sprite, mapHeader.numsprites); + G_LoadMapHack(mapname, md4, sprites.sprites.Data(), mapHeader.numsprites); if (CalcCRC32(buffer.Data(), buffer.Size() - 4) != nCRC) { @@ -882,7 +831,6 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect } if (pCRC) *pCRC = nCRC; - PropagateMarkerReferences(); if (encrypted) { if (gMattId == 0x7474614d || gMattId == 0x4d617474) @@ -908,9 +856,9 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect switch (header.version & 0xff) { case 0: - for (int i = 0; i < numsectors; i++) + for (auto& sect : sectors()) { - sectortype* pSector = §or[i]; + sectortype* pSector = § if (pSector->hasX()) { XSECTOR* pXSector = &pSector->xs(); @@ -932,9 +880,9 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect } [[fallthrough]]; case 1: - for (int i = 0; i < numsectors; i++) + for (auto& sect : sectors()) { - sectortype* pSector = §or[i]; + sectortype* pSector = § if (pSector->hasX()) { XSECTOR* pXSector = &pSector->xs(); @@ -943,9 +891,6 @@ void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sect } [[fallthrough]]; case 2: - for (int i = 0; i < kMaxSprites; i++) - { - } break; } @@ -964,8 +909,9 @@ END_BLD_NS // only used by the backup loader. void qloadboard(const char* filename, char flags, vec3_t* dapos, int16_t* daang) { + Blood::SpawnSpriteDef sprites; sectortype* sp; - Blood::dbLoadMap(filename, &dapos->x, &dapos->y, &dapos->z, daang, &sp, NULL); + Blood::dbLoadMap(filename, &dapos->x, &dapos->y, &dapos->z, daang, &sp, nullptr, sprites); Blood::dbInit(); // clean up immediately. } \ No newline at end of file diff --git a/source/games/blood/src/db.h b/source/games/blood/src/db.h index f66731ea5..d85bfdd13 100644 --- a/source/games/blood/src/db.h +++ b/source/games/blood/src/db.h @@ -74,7 +74,11 @@ struct MAPHEADER2 { #pragma pack(pop) -extern unsigned int gStatCount[kMaxStatus + 1];; +struct SpawnSpriteDef +{ + TArray sprites; + TArray xspr; +}; extern bool drawtile2048, encrypted; extern MAPHEADER2 byte_19AE44; @@ -125,7 +129,7 @@ int ChangeSpriteStat(int nSprite, int nStatus); void dbInit(void); void PropagateMarkerReferences(void); unsigned int dbReadMapCRC(const char *pPath); -void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sectortype** pSector, unsigned int* pCRC); +void dbLoadMap(const char* pPath, int* pX, int* pY, int* pZ, short* pAngle, sectortype** pSector, unsigned int* pCRC, SpawnSpriteDef& sprites); END_BLD_NS