From ffdb976f5b1888a5d7ccb0f9000a80577d391bf2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 29 Aug 2021 15:57:42 +0200 Subject: [PATCH] - marker stuff. --- source/games/blood/src/ai.cpp | 2 +- source/games/blood/src/bloodactor.h | 2 + source/games/blood/src/loadsave.cpp | 3 +- source/games/blood/src/nnexts.cpp | 89 ++++++++++++++++------------- source/games/blood/src/nnexts.h | 2 +- 5 files changed, 54 insertions(+), 44 deletions(-) diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index 475abc7f3..6fe501c80 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -1981,7 +1981,7 @@ void aiInitSprite(DBloodActor* actor) if (actor->GetTarget() == nullptr || actor->GetTarget()->s().type != kMarkerPath) { actor->SetTarget(nullptr); - aiPatrolSetMarker(pSprite, pXSprite); + aiPatrolSetMarker(actor); } if (stateTimer > 0) diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index 010e2817a..51843ea20 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -96,6 +96,7 @@ public: DUDEEXTRA dudeExtra; SPRITEMASS spriteMass; GENDUDEEXTRA genDudeExtra; + DBloodActor* prevmarker; // needed by the nnext marker code. This originally hijacked targetX in XSPRITE int cumulDamage; // this one's transient and does not need to be saved. bool explosionhackflag; // this originally hijacked the target field which is not safe when working with pointers. @@ -106,6 +107,7 @@ public: void Clear() { explosionhackflag = false; + prevmarker = nullptr; dudeSlope = 0; dudeExtra = {}; spriteMass = {}; diff --git a/source/games/blood/src/loadsave.cpp b/source/games/blood/src/loadsave.cpp index 0274a2d65..621851862 100644 --- a/source/games/blood/src/loadsave.cpp +++ b/source/games/blood/src/loadsave.cpp @@ -483,7 +483,8 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, DBloodActor& w, DB { arc("dudeslope", w.dudeSlope, def->dudeSlope) ("dudeextra", w.dudeExtra, def->dudeExtra) - ("explosionflag", w.explosionhackflag, def->explosionhackflag); + ("explosionflag", w.explosionhackflag, def->explosionhackflag) + ("prevmarker", w.prevmarker, def->prevmarker); if (gModernMap) { diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index bcc0f036d..36429677d 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -7761,35 +7761,37 @@ bool markerIsNode(DBloodActor* mark, bool back) // //--------------------------------------------------------------------------- -void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite) +void aiPatrolSetMarker(DBloodActor* actor) { - auto actor = &bloodActors[pSprite->index]; + auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); auto targetactor = actor->GetTarget(); - - spritetype* pNext = NULL; XSPRITE* pXNext = NULL; - spritetype* pPrev = NULL; XSPRITE* pXPrev = NULL; - int path = -1; int firstFinePath = -1; int prev = -1, next, i, closest = 200000; + DBloodActor* selected = nullptr; + int closest = 200000; // select closest marker that dude can see - if (pXSprite->target_i <= 0) { - + if (targetactor == nullptr) + { int zt1, zb1, zt2, zb2, dist; GetActorExtents(actor, &zt2, &zb2); - for (i = headspritestat[kStatPathMarker]; i != -1; i = nextspritestat[i]) { - - if (!xspriRangeIsFine(sprite[i].extra)) - continue; - pNext = &sprite[i]; pXNext = &xsprite[pNext->extra]; + BloodStatIterator it(kStatPathMarker); + while (auto nextactor = it.Next()) + { + if (!nextactor->hasX()) continue; + + auto pNext = &nextactor->s(); + auto pXNext = &nextactor->x(); + if (pXNext->locked || pXNext->isTriggered || pXNext->DudeLockout || (dist = approxDist(pNext->x - pSprite->x, pNext->y - pSprite->y)) > closest) continue; - GetSpriteExtents(pNext, &zt1, &zb1); + GetActorExtents(nextactor, &zt1, &zb1); if (cansee(pNext->x, pNext->y, zt1, pNext->sectnum, pSprite->x, pSprite->y, zt2, pSprite->sectnum)) { closest = dist; - path = pNext->index; + selected = nextactor; } } } @@ -7801,16 +7803,21 @@ void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite) // if reached marker is in radius of another marker with -3, but greater radius, use that marker // idea: for nodes only flag32 = specify if enemy must return back to node or allowed to select // another marker which belongs that node? + spritetype* pPrev = NULL; XSPRITE* pXPrev = NULL; + DBloodActor* prevactor = nullptr; + + DBloodActor* firstFinePath = nullptr; + int next; int breakChance = 0; auto pCur = &targetactor->s(); auto pXCur = &targetactor->x(); - if (pXSprite->targetX >= 0) + if (actor->prevmarker) { - pPrev = &sprite[pXSprite->targetX]; - pXPrev = &xsprite[pPrev->extra]; + prevactor = actor->prevmarker; + pPrev = &prevactor->s(); + pXPrev = &prevactor->x(); } - prev = pCur->index; bool node = markerIsNode(targetactor, false); pXSprite->unused2 = aiPatrolGetPathDir(pXSprite, pXCur); // decide if it should go back or forward @@ -7818,21 +7825,23 @@ void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite) pXSprite->unused2 = kPatrolMoveForward; bool back = (pXSprite->unused2 == kPatrolMoveBackward); next = (back) ? pXCur->data1 : pXCur->data2; - for (i = headspritestat[kStatPathMarker]; i != -1; i = nextspritestat[i]) { - - if (sprite[i].index == pXSprite->target_i || !xspriRangeIsFine(sprite[i].extra)) continue; - else if (pXSprite->targetX >= 0 && sprite[i].index == pPrev->index && node) { + BloodStatIterator it(kStatPathMarker); + while(auto nextactor = it.Next()) + { + if (nextactor == targetactor || !nextactor->hasX()) continue; + else if (pXSprite->targetX >= 0 && nextactor == prevactor && node) + { if (pXCur->data2 == pXPrev->data1) continue; } - pXNext = &xsprite[sprite[i].extra]; + auto pXNext = &nextactor->x(); if ((pXNext->locked || pXNext->isTriggered || pXNext->DudeLockout) || (back && pXNext->data2 != next) || (!back && pXNext->data1 != next)) continue; - if (firstFinePath == -1) firstFinePath = pXNext->reference; - if (aiPatrolMarkerBusy(&bloodActors[pSprite->index], &bloodActors[pXNext->reference]) && !Chance(0x0010)) continue; - else path = pXNext->reference; + if (firstFinePath == nullptr) firstFinePath = nextactor; + if (aiPatrolMarkerBusy(actor, nextactor) && !Chance(0x0010)) continue; + else selected = nextactor; breakChance += nnExtRandom(1, 5); if (breakChance >= 5) @@ -7840,25 +7849,22 @@ void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite) } - if (firstFinePath == -1) { - + if (firstFinePath == nullptr) + { viewSetSystemMessage("No markers with id #%d found for dude #%d! (back = %d)", next, pSprite->index, back); return; - } - if (path == -1) - path = firstFinePath; - + if (selected == nullptr) + selected = firstFinePath; } - if (!spriRangeIsFine(path)) + if (!selected) return; - pXSprite->target_i = path; - pXSprite->targetX = prev; // keep previous marker index here, use actual sprite coords when selecting direction - sprite[path].owner = pSprite->index; - + actor->SetTarget(selected); + selected->SetOwner(actor); + actor->prevmarker = targetactor; // keep previous marker index here, use actual sprite coords when selecting direction } //--------------------------------------------------------------------------- @@ -7876,6 +7882,7 @@ void aiPatrolStop(DBloodActor* actor, DBloodActor* targetactor, bool alarm) pXSprite->data3 = 0; // reset spot progress pXSprite->unused1 &= ~kDudeFlagCrouch; // reset the crouch status pXSprite->unused2 = kPatrolMoveForward; // reset path direction + actor->prevmarker = nullptr; pXSprite->targetX = -1; // reset the previous marker index if (pXSprite->health <= 0) return; @@ -8532,7 +8539,7 @@ void aiPatrolFlagsMgr(spritetype* pSource, XSPRITE* pXSource, spritetype* pDest, pXDest->stateTimer = 0; - aiPatrolSetMarker(pDest, pXDest); + aiPatrolSetMarker(destactor); if (spriteIsUnderwater(destactor)) aiPatrolState(destactor, kAiStatePatrolWaitW); else aiPatrolState(destactor, kAiStatePatrolWaitL); pXDest->data3 = 0; // reset the spot progress @@ -8637,7 +8644,7 @@ void aiPatrolThink(DBloodActor* actor) { } // move next marker - aiPatrolSetMarker(pSprite, pXSprite); + aiPatrolSetMarker(actor); } else if (aiPatrolTurning(pXSprite->aiState)) { @@ -8753,7 +8760,7 @@ void aiPatrolThink(DBloodActor* actor) { } // move the next marker - aiPatrolSetMarker(pSprite, pXSprite); + aiPatrolSetMarker(actor); } diff --git a/source/games/blood/src/nnexts.h b/source/games/blood/src/nnexts.h index 212c09100..155a66120 100644 --- a/source/games/blood/src/nnexts.h +++ b/source/games/blood/src/nnexts.h @@ -388,7 +388,7 @@ XSPRITE* evrListRedirectors(int objType, int objXIndex, XSPRITE* pXRedir, int* t int listTx(XSPRITE* pXRedir, int tx); void seqSpawnerOffSameTx(XSPRITE* pXSource); // ------------------------------------------------------------------------- // -void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite); +void aiPatrolSetMarker(DBloodActor* actor); void aiPatrolThink(DBloodActor* actor); void aiPatrolStop(DBloodActor* actor, DBloodActor* targetactor, bool alarm = false); void aiPatrolAlarmFull(spritetype* pSprite, XSPRITE* pXTarget, bool chain);