- marker stuff.

This commit is contained in:
Christoph Oelckers 2021-08-29 15:57:42 +02:00
parent af7164c91d
commit ffdb976f5b
5 changed files with 54 additions and 44 deletions

View file

@ -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)

View file

@ -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 = {};

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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);