mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-31 04:20:42 +00:00
- some more patrol code.
This commit is contained in:
parent
4ae32fb223
commit
146de69169
4 changed files with 100 additions and 84 deletions
|
@ -5089,7 +5089,7 @@ void MoveDude(DBloodActor* actor)
|
|||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (actor->IsDudeActor() && pXSprite->health > 0 && aiInPatrolState(nAiStateType))
|
||||
aiPatrolState(pSprite, kAiStatePatrolMoveL); // continue patrol when going from water
|
||||
aiPatrolState(actor, kAiStatePatrolMoveL); // continue patrol when going from water
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -5192,7 +5192,7 @@ void MoveDude(DBloodActor* actor)
|
|||
|
||||
// continue patrol when fall into water
|
||||
if (actor->IsDudeActor() && pXSprite->health > 0 && aiInPatrolState(nAiStateType))
|
||||
aiPatrolState(pSprite, kAiStatePatrolMoveW);
|
||||
aiPatrolState(actor, kAiStatePatrolMoveW);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -5632,7 +5632,7 @@ void actExplodeSprite(DBloodActor* actor)
|
|||
pSprite->flags &= ~3;
|
||||
pSprite->type = nType;
|
||||
const EXPLOSION* pExplodeInfo = &explodeInfo[nType];
|
||||
pXSprite->target_i = 0;
|
||||
actor->SetTarget(nullptr);
|
||||
pXSprite->data1 = pExplodeInfo->ticks;
|
||||
pXSprite->data2 = pExplodeInfo->quakeEffect;
|
||||
pXSprite->data3 = pExplodeInfo->flashEffect;
|
||||
|
|
|
@ -1978,21 +1978,22 @@ void aiInitSprite(DBloodActor* actor)
|
|||
|
||||
// make dude follow the markers
|
||||
bool uwater = spriteIsUnderwater(actor);
|
||||
if (pXSprite->target_i <= 0 || sprite[pXSprite->target_i].type != kMarkerPath)
|
||||
if (actor->GetTarget() == nullptr || actor->GetTarget()->s().type != kMarkerPath)
|
||||
{
|
||||
actor->SetTarget(nullptr);
|
||||
aiPatrolSetMarker(pSprite, pXSprite);
|
||||
}
|
||||
|
||||
if (stateTimer > 0) {
|
||||
if (uwater) aiPatrolState(pSprite, kAiStatePatrolWaitW);
|
||||
else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(pSprite, kAiStatePatrolWaitC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolWaitL);
|
||||
if (stateTimer > 0)
|
||||
{
|
||||
if (uwater) aiPatrolState(actor, kAiStatePatrolWaitW);
|
||||
else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(actor, kAiStatePatrolWaitC);
|
||||
else aiPatrolState(actor, kAiStatePatrolWaitL);
|
||||
pXSprite->stateTimer = stateTimer; // restore state timer
|
||||
}
|
||||
else if (uwater) aiPatrolState(pSprite, kAiStatePatrolMoveW);
|
||||
else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(pSprite, kAiStatePatrolMoveC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolMoveL);
|
||||
else if (uwater) aiPatrolState(actor, kAiStatePatrolMoveW);
|
||||
else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(actor, kAiStatePatrolMoveC);
|
||||
else aiPatrolState(actor, kAiStatePatrolMoveL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -4299,15 +4299,17 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH) {
|
|||
case 9: return (pXSpr->unused1 & kDudeFlagStealth);
|
||||
case 10: // check if the marker is busy with another dude
|
||||
case 11: // check if the marker is reached
|
||||
if (!pXSpr->dudeFlag4 || !spriRangeIsFine(pXSpr->target_i) || sprite[pXSpr->target_i].type != kMarkerPath) return false;
|
||||
if (!pXSpr->dudeFlag4 || !actor->GetTarget() || actor->GetTarget()->s().type != kMarkerPath) return false;
|
||||
switch (cond) {
|
||||
case 10:
|
||||
var = aiPatrolMarkerBusy(pSpr->index, pXSpr->target_i);
|
||||
if (!spriRangeIsFine(var)) return false;
|
||||
else if (PUSH) condPush(pXCond, OBJ_SPRITE, var);
|
||||
{
|
||||
auto var = aiPatrolMarkerBusy(actor, actor->GetTarget());
|
||||
if (!var) return false;
|
||||
else if (PUSH) condPush(pXCond, OBJ_SPRITE, var->s().index);
|
||||
break;
|
||||
}
|
||||
case 11:
|
||||
if (!aiPatrolMarkerReached(pSpr, pXSpr)) return false;
|
||||
if (!aiPatrolMarkerReached(actor)) return false;
|
||||
else if (PUSH) condPush(pXCond, OBJ_SPRITE, pXSpr->target_i);
|
||||
break;
|
||||
}
|
||||
|
@ -7541,18 +7543,23 @@ void nnExtAiSetDirection(DBloodActor* actor, int a3)
|
|||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
/// patrol functions
|
||||
// ------------------------------------------------
|
||||
void aiPatrolState(spritetype* pSprite, int state) {
|
||||
auto actor = &bloodActors[pSprite->index];
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
void aiPatrolState(DBloodActor* actor, int state)
|
||||
{
|
||||
spritetype* pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax && actor->hasX());
|
||||
assert(actor->GetTarget());
|
||||
|
||||
XSPRITE* pXSprite = &xsprite[pSprite->extra];
|
||||
assert(pXSprite->target_i >= 0 && pXSprite->target_i < kMaxSprites);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
|
||||
spritetype* pMarker = &sprite[pXSprite->target_i];
|
||||
XSPRITE* pXMarker = &xsprite[pMarker->extra];
|
||||
auto markeractor = actor->GetTarget();
|
||||
spritetype* pMarker = &markeractor->s();
|
||||
XSPRITE* pXMarker = &markeractor->x();
|
||||
assert(pMarker->type == kMarkerPath);
|
||||
|
||||
bool nSeqOverride = false, crouch = false;
|
||||
|
@ -7610,82 +7617,91 @@ void aiPatrolState(spritetype* pSprite, int state) {
|
|||
if (seq < 0)
|
||||
return aiPatrolStop(pSprite, -1);
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
|
||||
for (i = start; i < end; i++)
|
||||
{
|
||||
AISTATE* newState = &genPatrolStates[i];
|
||||
if (newState->stateType != state || (!nSeqOverride && seq != newState->seqId))
|
||||
continue;
|
||||
|
||||
if (pSprite->type == kDudeModernCustom) aiGenDudeNewState(actor, newState);
|
||||
else aiNewState(&bloodActors[pXSprite->reference], newState);
|
||||
else aiNewState(actor, newState);
|
||||
|
||||
if (crouch) pXSprite->unused1 |= kDudeFlagCrouch;
|
||||
else pXSprite->unused1 &= ~kDudeFlagCrouch;
|
||||
|
||||
if (nSeqOverride)
|
||||
seqSpawn(seq, OBJ_SPRITE, pSprite->extra);
|
||||
seqSpawn(seq, actor);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (i == end) {
|
||||
viewSetSystemMessage("No patrol state #%d found for dude #%d (type = %d)", state, pSprite->index, pSprite->type);
|
||||
if (i == end)
|
||||
{
|
||||
viewSetSystemMessage("No patrol state #%d found for dude #%d (type = %d)", state, actor->GetIndex(), pSprite->type);
|
||||
aiPatrolStop(pSprite, -1);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// check if some dude already follows the given marker
|
||||
int aiPatrolMarkerBusy(int nExcept, int nMarker) {
|
||||
for (int i = headspritestat[kStatDude]; i != -1; i = nextspritestat[i]) {
|
||||
if (!IsDudeSprite(&sprite[i]) || sprite[i].index == nExcept || !xspriRangeIsFine(sprite[i].extra))
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DBloodActor* aiPatrolMarkerBusy(DBloodActor* except, DBloodActor* marker)
|
||||
{
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor = it.Next())
|
||||
{
|
||||
if (!actor->IsDudeActor() || actor == except || !actor->hasX())
|
||||
continue;
|
||||
|
||||
XSPRITE* pXDude = &xsprite[sprite[i].extra];
|
||||
if (pXDude->health > 0 && pXDude->target_i >= 0 && sprite[pXDude->target_i].type == kMarkerPath && pXDude->target_i == nMarker)
|
||||
return sprite[i].index;
|
||||
auto targ = actor->GetTarget();
|
||||
if (actor->x().health > 0 && targ != nullptr && targ->s().type == kMarkerPath && targ == marker)
|
||||
return actor;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// check if some dude already follows the given marker
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool aiPatrolMarkerReached(spritetype* pSprite, XSPRITE* pXSprite) {
|
||||
|
||||
bool aiPatrolMarkerReached(DBloodActor* actor)
|
||||
{
|
||||
spritetype* pSprite = &actor->s();
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
|
||||
auto actor = &bloodActors[pSprite->index];
|
||||
const DUDEINFO_EXTRA* pExtra = &gDudeInfoExtra[pSprite->type - kDudeBase];
|
||||
if (spriRangeIsFine(pXSprite->target_i) && sprite[pXSprite->target_i].type == kMarkerPath) {
|
||||
|
||||
spritetype* pMarker = &sprite[pXSprite->target_i];
|
||||
short okDist = ClipLow(pMarker->clipdist << 1, 4);
|
||||
auto markeractor = actor->GetTarget();
|
||||
if (markeractor && markeractor->s().type == kMarkerPath)
|
||||
{
|
||||
spritetype* pMarker = &markeractor->s();
|
||||
int okDist = ClipLow(pMarker->clipdist << 1, 4);
|
||||
int oX = abs(pMarker->x - pSprite->x) >> 4;
|
||||
int oY = abs(pMarker->y - pSprite->y) >> 4;
|
||||
|
||||
if (approxDist(oX, oY) <= okDist) {
|
||||
|
||||
if (spriteIsUnderwater(actor) || pExtra->flying) {
|
||||
|
||||
if (approxDist(oX, oY) <= okDist)
|
||||
{
|
||||
if (spriteIsUnderwater(actor) || pExtra->flying)
|
||||
{
|
||||
okDist = pMarker->clipdist << 4;
|
||||
int ztop, zbot, ztop2, zbot2;
|
||||
GetSpriteExtents(pSprite, &ztop, &zbot);
|
||||
GetSpriteExtents(pMarker, &ztop2, &zbot2);
|
||||
GetActorExtents(actor, &ztop, &zbot);
|
||||
GetActorExtents(markeractor, &ztop2, &zbot2);
|
||||
|
||||
int oZ1 = abs(zbot - ztop2) >> 6;
|
||||
int oZ2 = abs(ztop - zbot2) >> 6;
|
||||
if (oZ1 > okDist && oZ2 > okDist)
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
int findNextMarker(XSPRITE* pXMark, bool back) {
|
||||
|
@ -7793,7 +7809,7 @@ void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite) {
|
|||
continue;
|
||||
|
||||
if (firstFinePath == -1) firstFinePath = pXNext->reference;
|
||||
if (aiPatrolMarkerBusy(pSprite->index, pXNext->reference) >= 0 && !Chance(0x0010)) continue;
|
||||
if (aiPatrolMarkerBusy(&bloodActors[pSprite->index], &bloodActors[pXNext->reference]) && !Chance(0x0010)) continue;
|
||||
else path = pXNext->reference;
|
||||
|
||||
breakChance += nnExtRandom(1, 5);
|
||||
|
@ -7941,12 +7957,11 @@ void aiPatrolMove(DBloodActor* actor) {
|
|||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
|
||||
if (abs(nAng) > goalAng || ((pXTarget->waitTime > 0 || pXTarget->data1 == pXTarget->data2) && aiPatrolMarkerReached(pSprite, pXSprite))) {
|
||||
|
||||
if (abs(nAng) > goalAng || ((pXTarget->waitTime > 0 || pXTarget->data1 == pXTarget->data2) && aiPatrolMarkerReached(actor)))
|
||||
{
|
||||
actor->xvel() = 0;
|
||||
actor->yvel() = 0;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (gSpriteHit[pSprite->extra].hit.type == kHitSprite)
|
||||
|
@ -8473,8 +8488,8 @@ void aiPatrolFlagsMgr(spritetype* pSource, XSPRITE* pXSource, spritetype* pDest,
|
|||
|
||||
|
||||
aiPatrolSetMarker(pDest, pXDest);
|
||||
if (spriteIsUnderwater(destactor)) aiPatrolState(pDest, kAiStatePatrolWaitW);
|
||||
else aiPatrolState(pDest, kAiStatePatrolWaitL);
|
||||
if (spriteIsUnderwater(destactor)) aiPatrolState(destactor, kAiStatePatrolWaitW);
|
||||
else aiPatrolState(destactor, kAiStatePatrolWaitL);
|
||||
pXDest->data3 = 0; // reset the spot progress
|
||||
|
||||
}
|
||||
|
@ -8534,9 +8549,9 @@ void aiPatrolThink(DBloodActor* actor) {
|
|||
|
||||
if (--pXSprite->unused4 <= 0) {
|
||||
|
||||
if (uwater) aiPatrolState(pSprite, kAiStatePatrolTurnW);
|
||||
else if (crouch) aiPatrolState(pSprite, kAiStatePatrolTurnC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolTurnL);
|
||||
if (uwater) aiPatrolState(actor, kAiStatePatrolTurnW);
|
||||
else if (crouch) aiPatrolState(actor, kAiStatePatrolTurnC);
|
||||
else aiPatrolState(actor, kAiStatePatrolTurnL);
|
||||
pXSprite->unused4 = kMinPatrolTurnDelay + Random(kPatrolTurnDelayRange);
|
||||
|
||||
}
|
||||
|
@ -8587,9 +8602,9 @@ void aiPatrolThink(DBloodActor* actor) {
|
|||
// save imer for waiting
|
||||
stateTimer = pXSprite->stateTimer;
|
||||
|
||||
if (uwater) aiPatrolState(pSprite, kAiStatePatrolWaitW);
|
||||
else if (crouch) aiPatrolState(pSprite, kAiStatePatrolWaitC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolWaitL);
|
||||
if (uwater) aiPatrolState(actor, kAiStatePatrolWaitW);
|
||||
else if (crouch) aiPatrolState(actor, kAiStatePatrolWaitC);
|
||||
else aiPatrolState(actor, kAiStatePatrolWaitL);
|
||||
|
||||
// must restore it
|
||||
pXSprite->stateTimer = stateTimer;
|
||||
|
@ -8599,7 +8614,7 @@ void aiPatrolThink(DBloodActor* actor) {
|
|||
|
||||
return;
|
||||
|
||||
} else if ((reached = aiPatrolMarkerReached(pSprite, pXSprite)) == true) {
|
||||
} else if ((reached = aiPatrolMarkerReached(actor)) == true) {
|
||||
|
||||
pXMarker->isTriggered = pXMarker->triggerOnce; // can't select this marker for path anymore if true
|
||||
|
||||
|
@ -8622,8 +8637,8 @@ void aiPatrolThink(DBloodActor* actor) {
|
|||
|
||||
}
|
||||
|
||||
if (pMarker->owner == pSprite->index)
|
||||
pMarker->owner = aiPatrolMarkerBusy(pSprite->index, pMarker->index);
|
||||
if (markeractor->GetOwner() == actor)
|
||||
markeractor->SetOwner(aiPatrolMarkerBusy(actor, markeractor));
|
||||
|
||||
// trigger at arrival
|
||||
if (pXMarker->triggerOn) {
|
||||
|
@ -8644,9 +8659,9 @@ void aiPatrolThink(DBloodActor* actor) {
|
|||
|
||||
}
|
||||
|
||||
if (uwater) aiPatrolState(pSprite, kAiStatePatrolWaitW);
|
||||
else if (crouch) aiPatrolState(pSprite, kAiStatePatrolWaitC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolWaitL);
|
||||
if (uwater) aiPatrolState(actor, kAiStatePatrolWaitW);
|
||||
else if (crouch) aiPatrolState(actor, kAiStatePatrolWaitC);
|
||||
else aiPatrolState(actor, kAiStatePatrolWaitL);
|
||||
|
||||
if (pXMarker->waitTime)
|
||||
pXSprite->stateTimer = (pXMarker->waitTime * 120) / 10;
|
||||
|
@ -8660,9 +8675,9 @@ void aiPatrolThink(DBloodActor* actor) {
|
|||
|
||||
} else {
|
||||
|
||||
if (pMarker->owner == pSprite->index)
|
||||
pMarker->owner = aiPatrolMarkerBusy(pSprite->index, pMarker->index);
|
||||
|
||||
if (markeractor->GetOwner() == actor)
|
||||
markeractor->SetOwner(aiPatrolMarkerBusy(actor, markeractor));
|
||||
|
||||
if (pXMarker->triggerOn || pXMarker->triggerOff) {
|
||||
|
||||
if (pXMarker->txID) {
|
||||
|
@ -8702,9 +8717,9 @@ void aiPatrolThink(DBloodActor* actor) {
|
|||
nnExtAiSetDirection(actor, getangle(pMarker->x - pSprite->x, pMarker->y - pSprite->y));
|
||||
|
||||
if (aiPatrolMoving(pXSprite->aiState) && !reached) return;
|
||||
else if (uwater) aiPatrolState(pSprite, kAiStatePatrolMoveW);
|
||||
else if (crouch) aiPatrolState(pSprite, kAiStatePatrolMoveC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolMoveL);
|
||||
else if (uwater) aiPatrolState(actor, kAiStatePatrolMoveW);
|
||||
else if (crouch) aiPatrolState(actor, kAiStatePatrolMoveC);
|
||||
else aiPatrolState(actor, kAiStatePatrolMoveL);
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
|
@ -393,10 +393,10 @@ void aiPatrolThink(DBloodActor* actor);
|
|||
void aiPatrolStop(spritetype* pSprite, int target, bool alarm = false);
|
||||
void aiPatrolAlarmFull(spritetype* pSprite, XSPRITE* pXTarget, bool chain);
|
||||
void aiPatrolAlarmLite(spritetype* pSprite, XSPRITE* pXTarget);
|
||||
void aiPatrolState(spritetype* pSprite, int state);
|
||||
void aiPatrolState(DBloodActor* pSprite, int state);
|
||||
void aiPatrolMove(DBloodActor* actor);
|
||||
int aiPatrolMarkerBusy(int nExcept, int nMarker);
|
||||
bool aiPatrolMarkerReached(spritetype* pSprite, XSPRITE* pXSprite);
|
||||
DBloodActor* aiPatrolMarkerBusy(DBloodActor* except, DBloodActor* marker);
|
||||
bool aiPatrolMarkerReached(DBloodActor*);
|
||||
bool aiPatrolGetPathDir(XSPRITE* pXSprite, XSPRITE* pXMarker);
|
||||
void aiPatrolFlagsMgr(spritetype* pSource, XSPRITE* pXSource, spritetype* pDest, XSPRITE* pXDest, bool copy, bool init);
|
||||
void aiPatrolRandGoalAng(DBloodActor* actor);
|
||||
|
|
Loading…
Reference in a new issue