- reformatted the actor and ai sources.

This commit is contained in:
Christoph Oelckers 2021-09-16 21:59:39 +02:00
parent 0ee81b2bb8
commit c485fce958
21 changed files with 7350 additions and 7349 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -43,403 +43,403 @@ static void batMoveFly(DBloodActor*);
static void batMoveToCeil(DBloodActor*); static void batMoveToCeil(DBloodActor*);
AISTATE batIdle = {kAiStateIdle, 0, -1, 0, NULL, NULL, batThinkTarget, NULL }; AISTATE batIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, batThinkTarget, NULL };
AISTATE batFlyIdle = {kAiStateIdle, 6, -1, 0, NULL, NULL, batThinkTarget, NULL }; AISTATE batFlyIdle = { kAiStateIdle, 6, -1, 0, NULL, NULL, batThinkTarget, NULL };
AISTATE batChase = {kAiStateChase, 6, -1, 0, NULL, batMoveForward, batThinkChase, &batFlyIdle }; AISTATE batChase = { kAiStateChase, 6, -1, 0, NULL, batMoveForward, batThinkChase, &batFlyIdle };
AISTATE batPonder = {kAiStateOther, 6, -1, 0, NULL, NULL, batThinkPonder, NULL }; AISTATE batPonder = { kAiStateOther, 6, -1, 0, NULL, NULL, batThinkPonder, NULL };
AISTATE batGoto = {kAiStateMove, 6, -1, 600, NULL, batMoveForward, batThinkGoto, &batFlyIdle }; AISTATE batGoto = { kAiStateMove, 6, -1, 600, NULL, batMoveForward, batThinkGoto, &batFlyIdle };
AISTATE batBite = {kAiStateChase, 7, nBatBiteClient, 60, NULL, NULL, NULL, &batPonder }; AISTATE batBite = { kAiStateChase, 7, nBatBiteClient, 60, NULL, NULL, NULL, &batPonder };
AISTATE batRecoil = {kAiStateRecoil, 5, -1, 0, NULL, NULL, NULL, &batChase }; AISTATE batRecoil = { kAiStateRecoil, 5, -1, 0, NULL, NULL, NULL, &batChase };
AISTATE batSearch = {kAiStateSearch, 6, -1, 120, NULL, batMoveForward, batThinkSearch, &batFlyIdle }; AISTATE batSearch = { kAiStateSearch, 6, -1, 120, NULL, batMoveForward, batThinkSearch, &batFlyIdle };
AISTATE batSwoop = {kAiStateOther, 6, -1, 60, NULL, batMoveSwoop, batThinkChase, &batChase }; AISTATE batSwoop = { kAiStateOther, 6, -1, 60, NULL, batMoveSwoop, batThinkChase, &batChase };
AISTATE batFly = { kAiStateMove, 6, -1, 0, NULL, batMoveFly, batThinkChase, &batChase }; AISTATE batFly = { kAiStateMove, 6, -1, 0, NULL, batMoveFly, batThinkChase, &batChase };
AISTATE batTurn = {kAiStateMove, 6, -1, 60, NULL, aiMoveTurn, NULL, &batChase }; AISTATE batTurn = { kAiStateMove, 6, -1, 60, NULL, aiMoveTurn, NULL, &batChase };
AISTATE batHide = {kAiStateOther, 6, -1, 0, NULL, batMoveToCeil, batMoveForward, NULL }; AISTATE batHide = { kAiStateOther, 6, -1, 0, NULL, batMoveToCeil, batMoveForward, NULL };
AISTATE batDodgeUp = {kAiStateMove, 6, -1, 120, NULL, batMoveDodgeUp, 0, &batChase }; AISTATE batDodgeUp = { kAiStateMove, 6, -1, 120, NULL, batMoveDodgeUp, 0, &batChase };
AISTATE batDodgeUpRight = {kAiStateMove, 6, -1, 90, NULL, batMoveDodgeUp, 0, &batChase }; AISTATE batDodgeUpRight = { kAiStateMove, 6, -1, 90, NULL, batMoveDodgeUp, 0, &batChase };
AISTATE batDodgeUpLeft = {kAiStateMove, 6, -1, 90, NULL, batMoveDodgeUp, 0, &batChase }; AISTATE batDodgeUpLeft = { kAiStateMove, 6, -1, 90, NULL, batMoveDodgeUp, 0, &batChase };
AISTATE batDodgeDown = {kAiStateMove, 6, -1, 120, NULL, batMoveDodgeDown, 0, &batChase }; AISTATE batDodgeDown = { kAiStateMove, 6, -1, 120, NULL, batMoveDodgeDown, 0, &batChase };
AISTATE batDodgeDownRight = {kAiStateMove, 6, -1, 90, NULL, batMoveDodgeDown, 0, &batChase }; AISTATE batDodgeDownRight = { kAiStateMove, 6, -1, 90, NULL, batMoveDodgeDown, 0, &batChase };
AISTATE batDodgeDownLeft = {kAiStateMove, 6, -1, 90, NULL, batMoveDodgeDown, 0, &batChase }; AISTATE batDodgeDownLeft = { kAiStateMove, 6, -1, 90, NULL, batMoveDodgeDown, 0, &batChase };
void batBiteSeqCallback(int, DBloodActor* actor) void batBiteSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype *pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type); DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
int height = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2; int height = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2;
int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2; int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2;
actFireVector(actor, 0, 0, dx, dy, height2-height, kVectorBatBite); actFireVector(actor, 0, 0, dx, dy, height2 - height, kVectorBatBite);
} }
static void batThinkTarget(DBloodActor* actor) static void batThinkTarget(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10) if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++; pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D *pTarget = &actor->basePoint(); POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &batTurn); aiNewState(actor, &batTurn);
return; return;
} }
if (Chance(pDudeInfo->alertChance)) if (Chance(pDudeInfo->alertChance))
{ {
for (int p = connecthead; p >= 0; p = connectpoint2[p]) for (int p = connecthead; p >= 0; p = connectpoint2[p])
{ {
PLAYER *pPlayer = &gPlayer[p]; PLAYER* pPlayer = &gPlayer[p];
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0) if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
continue; continue;
int x = pPlayer->pSprite->x; int x = pPlayer->pSprite->x;
int y = pPlayer->pSprite->y; int y = pPlayer->pSprite->y;
int z = pPlayer->pSprite->z; int z = pPlayer->pSprite->z;
int nSector = pPlayer->pSprite->sectnum; int nSector = pPlayer->pSprite->sectnum;
int dx = x-pSprite->x; int dx = x - pSprite->x;
int dy = y-pSprite->y; int dy = y - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist) if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
continue; continue;
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum)) if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
continue; continue;
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, pPlayer->actor()); aiSetTarget(actor, pPlayer->actor());
aiActivateDude(actor); aiActivateDude(actor);
} }
else if (nDist < pDudeInfo->hearDist) else if (nDist < pDudeInfo->hearDist)
{ {
aiSetTarget(actor, x, y, z); aiSetTarget(actor, x, y, z);
aiActivateDude(actor); aiActivateDude(actor);
} }
else else
continue; continue;
break; break;
} }
} }
} }
static void batThinkSearch(DBloodActor* actor) static void batThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor, pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
batThinkTarget(actor); batThinkTarget(actor);
} }
static void batThinkGoto(DBloodActor* actor) static void batThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor, nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &batSearch); aiNewState(actor, &batSearch);
batThinkTarget(actor); batThinkTarget(actor);
} }
static void batThinkPonder(DBloodActor* actor) static void batThinkPonder(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &batSearch); aiNewState(actor, &batSearch);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE *pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor, getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &batSearch); aiNewState(actor, &batSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
int height2 = (getDudeInfo(pTarget->type)->eyeHeight*pTarget->yrepeat)<<2; int height2 = (getDudeInfo(pTarget->type)->eyeHeight * pTarget->yrepeat) << 2;
int top, bottom; int top, bottom;
GetActorExtents(actor, &top, &bottom); GetActorExtents(actor, &top, &bottom);
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (height2-height < 0x3000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) if (height2 - height < 0x3000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
aiNewState(actor, &batDodgeUp); aiNewState(actor, &batDodgeUp);
else if (height2-height > 0x5000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) else if (height2 - height > 0x5000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
aiNewState(actor, &batDodgeDown); aiNewState(actor, &batDodgeDown);
else if (height2-height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85) else if (height2 - height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85)
aiNewState(actor, &batDodgeUp); aiNewState(actor, &batDodgeUp);
else if (height2-height > 0x6000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85) else if (height2 - height > 0x6000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
aiNewState(actor, &batDodgeDown); aiNewState(actor, &batDodgeDown);
else if (height2-height < 0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85) else if (height2 - height < 0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
aiNewState(actor, &batDodgeUp); aiNewState(actor, &batDodgeUp);
else if (height2-height < 0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400) else if (height2 - height < 0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400)
aiNewState(actor, &batDodgeUp); aiNewState(actor, &batDodgeUp);
else if (height2-height > 0x4000) else if (height2 - height > 0x4000)
aiNewState(actor, &batDodgeDown); aiNewState(actor, &batDodgeDown);
else else
aiNewState(actor, &batDodgeUp); aiNewState(actor, &batDodgeUp);
return; return;
} }
} }
aiNewState(actor, &batGoto); aiNewState(actor, &batGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void batMoveDodgeUp(DBloodActor* actor) static void batMoveDodgeUp(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int dx = actor->xvel(); int dx = actor->xvel();
int dy = actor->yvel(); int dy = actor->yvel();
int t1 = DMulScale(dx, nCos, dy, nSin, 30); int t1 = DMulScale(dx, nCos, dy, nSin, 30);
int t2 = DMulScale(dx, nSin, -dy, nCos, 30); int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
if (pXSprite->dodgeDir > 0) if (pXSprite->dodgeDir > 0)
t2 += pDudeInfo->sideSpeed; t2 += pDudeInfo->sideSpeed;
else else
t2 -= pDudeInfo->sideSpeed; t2 -= pDudeInfo->sideSpeed;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = -0x52aaa; actor->zvel() = -0x52aaa;
} }
static void batMoveDodgeDown(DBloodActor* actor) static void batMoveDodgeDown(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
if (pXSprite->dodgeDir == 0) if (pXSprite->dodgeDir == 0)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int dx = actor->xvel(); int dx = actor->xvel();
int dy = actor->yvel(); int dy = actor->yvel();
int t1 = DMulScale(dx, nCos, dy, nSin, 30); int t1 = DMulScale(dx, nCos, dy, nSin, 30);
int t2 = DMulScale(dx, nSin, -dy, nCos, 30); int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
if (pXSprite->dodgeDir > 0) if (pXSprite->dodgeDir > 0)
t2 += pDudeInfo->sideSpeed; t2 += pDudeInfo->sideSpeed;
else else
t2 -= pDudeInfo->sideSpeed; t2 -= pDudeInfo->sideSpeed;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = 0x44444; actor->zvel() = 0x44444;
} }
static void batThinkChase(DBloodActor* actor) static void batThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &batGoto); aiNewState(actor, &batGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor, getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &batSearch); aiNewState(actor, &batSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &batSearch); aiNewState(actor, &batSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
// Should be dudeInfo[pTarget->type-kDudeBase] // Should be dudeInfo[pTarget->type-kDudeBase]
int height2 = (pDudeInfo->eyeHeight*pTarget->yrepeat)<<2; int height2 = (pDudeInfo->eyeHeight * pTarget->yrepeat) << 2;
int top, bottom; int top, bottom;
GetActorExtents(actor, &top, &bottom); GetActorExtents(actor, &top, &bottom);
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
int floorZ = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y); int floorZ = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
if (height2-height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85) if (height2 - height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85)
aiNewState(actor, &batBite); aiNewState(actor, &batBite);
else if ((height2-height > 0x5000 || floorZ-bottom > 0x5000) && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85) else if ((height2 - height > 0x5000 || floorZ - bottom > 0x5000) && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
aiNewState(actor, &batSwoop); aiNewState(actor, &batSwoop);
else if ((height2-height < 0x3000 || floorZ-bottom < 0x3000) && abs(nDeltaAngle) < 85) else if ((height2 - height < 0x3000 || floorZ - bottom < 0x3000) && abs(nDeltaAngle) < 85)
aiNewState(actor, &batFly); aiNewState(actor, &batFly);
return; return;
} }
} }
else else
{ {
aiNewState(actor, &batFly); aiNewState(actor, &batFly);
return; return;
} }
} }
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
aiNewState(actor, &batHide); aiNewState(actor, &batHide);
} }
static void batMoveForward(DBloodActor* actor) static void batMoveForward(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = pDudeInfo->frontSpeed<<2; int nAccel = pDudeInfo->frontSpeed << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
return; return;
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
pSprite->ang = (pSprite->ang+256)&2047; pSprite->ang = (pSprite->ang + 256) & 2047;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if ((unsigned int)Random(64) < 32 && nDist <= 0x200) if ((unsigned int)Random(64) < 32 && nDist <= 0x200)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
t1 += nAccel; t1 += nAccel;
else else
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
} }
static void batMoveSwoop(DBloodActor* actor) static void batMoveSwoop(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = pDudeInfo->frontSpeed<<2; int nAccel = pDudeInfo->frontSpeed << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
{ {
pXSprite->goalAng = (pSprite->ang+512)&2047; pXSprite->goalAng = (pSprite->ang + 512) & 2047;
return; return;
} }
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x600) && nDist <= 0x200) if (Chance(0x600) && nDist <= 0x200)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = 0x44444; actor->zvel() = 0x44444;
} }
static void batMoveFly(DBloodActor* actor) static void batMoveFly(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = pDudeInfo->frontSpeed<<2; int nAccel = pDudeInfo->frontSpeed << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
{ {
pSprite->ang = (pSprite->ang+512)&2047; pSprite->ang = (pSprite->ang + 512) & 2047;
return; return;
} }
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x4000) && nDist <= 0x200) if (Chance(0x4000) && nDist <= 0x200)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = -0x2d555; actor->zvel() = -0x2d555;
} }
void batMoveToCeil(DBloodActor* actor) void batMoveToCeil(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = pSprite->z; int z = pSprite->z;
int nSector = pSprite->sectnum; int nSector = pSprite->sectnum;
if (z - pXSprite->targetZ < 0x1000) if (z - pXSprite->targetZ < 0x1000)
{ {
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
pSprite->flags = 0; pSprite->flags = 0;
aiNewState(actor, &batIdle); aiNewState(actor, &batIdle);
} }
else else
aiSetTarget(actor, x, y, sector[nSector].ceilingz); aiSetTarget(actor, x, y, sector[nSector].ceilingz);
} }
END_BLD_NS END_BLD_NS

File diff suppressed because it is too large Load diff

View file

@ -29,17 +29,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void eelThinkTarget(DBloodActor *); static void eelThinkTarget(DBloodActor*);
static void eelThinkSearch(DBloodActor *); static void eelThinkSearch(DBloodActor*);
static void eelThinkGoto(DBloodActor *); static void eelThinkGoto(DBloodActor*);
static void eelThinkPonder(DBloodActor *); static void eelThinkPonder(DBloodActor*);
static void eelMoveDodgeUp(DBloodActor *); static void eelMoveDodgeUp(DBloodActor*);
static void eelMoveDodgeDown(DBloodActor *); static void eelMoveDodgeDown(DBloodActor*);
static void eelThinkChase(DBloodActor *); static void eelThinkChase(DBloodActor*);
static void eelMoveForward(DBloodActor *); static void eelMoveForward(DBloodActor*);
static void eelMoveSwoop(DBloodActor *); static void eelMoveSwoop(DBloodActor*);
static void eelMoveAscend(DBloodActor *actor); static void eelMoveAscend(DBloodActor* actor);
static void eelMoveToCeil(DBloodActor *); static void eelMoveToCeil(DBloodActor*);
AISTATE eelIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, eelThinkTarget, NULL }; AISTATE eelIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, eelThinkTarget, NULL };
@ -63,385 +63,385 @@ AISTATE eelDodgeDownLeft = { kAiStateMove, 0, -1, 90, NULL, eelMoveDodgeDown, NU
void eelBiteSeqCallback(int, DBloodActor* actor) void eelBiteSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype *pSprite = &actor->s(); spritetype* pSprite = &actor->s();
/* /*
* workaround for * workaround for
* pXSprite->target >= 0 && pXSprite->target < kMaxSprites in file NBlood/source/blood/src/aiboneel.cpp at line 86 * pXSprite->target >= 0 && pXSprite->target < kMaxSprites in file NBlood/source/blood/src/aiboneel.cpp at line 86
* The value of pXSprite->target is -1. * The value of pXSprite->target is -1.
* copied from lines 177:181 * copied from lines 177:181
* resolves this case, but may cause other issues? * resolves this case, but may cause other issues?
*/ */
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &eelSearch); aiNewState(actor, &eelSearch);
return; return;
} }
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type); DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
int height = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2; int height = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2;
int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2; int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2;
actFireVector(actor, 0, 0, dx, dy, height2-height, kVectorBoneelBite); actFireVector(actor, 0, 0, dx, dy, height2 - height, kVectorBoneelBite);
} }
static void eelThinkTarget(DBloodActor* actor) static void eelThinkTarget(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10) if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++; pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D* pTarget = &actor->basePoint(); POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &eelTurn); aiNewState(actor, &eelTurn);
return; return;
} }
if (Chance(pDudeInfo->alertChance)) if (Chance(pDudeInfo->alertChance))
{ {
for (int p = connecthead; p >= 0; p = connectpoint2[p]) for (int p = connecthead; p >= 0; p = connectpoint2[p])
{ {
PLAYER *pPlayer = &gPlayer[p]; PLAYER* pPlayer = &gPlayer[p];
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0) if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
continue; continue;
int x = pPlayer->pSprite->x; int x = pPlayer->pSprite->x;
int y = pPlayer->pSprite->y; int y = pPlayer->pSprite->y;
int z = pPlayer->pSprite->z; int z = pPlayer->pSprite->z;
int nSector = pPlayer->pSprite->sectnum; int nSector = pPlayer->pSprite->sectnum;
int dx = x-pSprite->x; int dx = x - pSprite->x;
int dy = y-pSprite->y; int dy = y - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist) if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
continue; continue;
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum)) if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
continue; continue;
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
aiSetTarget(actor, pPlayer->actor()); aiSetTarget(actor, pPlayer->actor());
aiActivateDude(actor); aiActivateDude(actor);
} }
else if (nDist < pDudeInfo->hearDist) else if (nDist < pDudeInfo->hearDist)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
aiSetTarget(actor, x, y, z); aiSetTarget(actor, x, y, z);
aiActivateDude(actor); aiActivateDude(actor);
} }
else else
continue; continue;
break; break;
} }
} }
} }
static void eelThinkSearch(DBloodActor* actor) static void eelThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
eelThinkTarget(actor); eelThinkTarget(actor);
} }
static void eelThinkGoto(DBloodActor* actor) static void eelThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &eelSearch); aiNewState(actor, &eelSearch);
eelThinkTarget(actor); eelThinkTarget(actor);
} }
static void eelThinkPonder(DBloodActor* actor) static void eelThinkPonder(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &eelSearch); aiNewState(actor, &eelSearch);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &eelSearch); aiNewState(actor, &eelSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
int height2 = (getDudeInfo(pTarget->type)->eyeHeight*pTarget->yrepeat)<<2; int height2 = (getDudeInfo(pTarget->type)->eyeHeight * pTarget->yrepeat) << 2;
int top, bottom; int top, bottom;
GetActorExtents(actor, &top, &bottom); GetActorExtents(actor, &top, &bottom);
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (height2-height < -0x2000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) if (height2 - height < -0x2000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelDodgeUp); aiNewState(actor, &eelDodgeUp);
else if (height2-height > 0xccc && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) else if (height2 - height > 0xccc && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelDodgeDown); aiNewState(actor, &eelDodgeDown);
else if (height2-height < 0xccc && nDist < 0x399 && abs(nDeltaAngle) < 85) else if (height2 - height < 0xccc && nDist < 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelDodgeUp); aiNewState(actor, &eelDodgeUp);
else if (height2-height > 0xccc && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85) else if (height2 - height > 0xccc && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelDodgeDown); aiNewState(actor, &eelDodgeDown);
else if (height2-height < -0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85) else if (height2 - height < -0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelDodgeUp); aiNewState(actor, &eelDodgeUp);
else if (height2-height < -0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400) else if (height2 - height < -0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400)
aiNewState(actor, &eelDodgeUp); aiNewState(actor, &eelDodgeUp);
else if (height2-height > 0xccc) else if (height2 - height > 0xccc)
aiNewState(actor, &eelDodgeDown); aiNewState(actor, &eelDodgeDown);
else else
aiNewState(actor, &eelDodgeUp); aiNewState(actor, &eelDodgeUp);
return; return;
} }
} }
aiNewState(actor, &eelGoto); aiNewState(actor, &eelGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void eelMoveDodgeUp(DBloodActor* actor) static void eelMoveDodgeUp(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int dx = actor->xvel(); int dx = actor->xvel();
int dy = actor->yvel(); int dy = actor->yvel();
int t1 = DMulScale(dx, nCos, dy, nSin, 30); int t1 = DMulScale(dx, nCos, dy, nSin, 30);
int t2 = DMulScale(dx, nSin, -dy, nCos, 30); int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
if (pXSprite->dodgeDir > 0) if (pXSprite->dodgeDir > 0)
t2 += pDudeInfo->sideSpeed; t2 += pDudeInfo->sideSpeed;
else else
t2 -= pDudeInfo->sideSpeed; t2 -= pDudeInfo->sideSpeed;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = -0x8000; actor->zvel() = -0x8000;
} }
static void eelMoveDodgeDown(DBloodActor* actor) static void eelMoveDodgeDown(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
if (pXSprite->dodgeDir == 0) if (pXSprite->dodgeDir == 0)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int dx = actor->xvel(); int dx = actor->xvel();
int dy = actor->yvel(); int dy = actor->yvel();
int t1 = DMulScale(dx, nCos, dy, nSin, 30); int t1 = DMulScale(dx, nCos, dy, nSin, 30);
int t2 = DMulScale(dx, nSin, -dy, nCos, 30); int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
if (pXSprite->dodgeDir > 0) if (pXSprite->dodgeDir > 0)
t2 += pDudeInfo->sideSpeed; t2 += pDudeInfo->sideSpeed;
else else
t2 -= pDudeInfo->sideSpeed; t2 -= pDudeInfo->sideSpeed;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = 0x44444; actor->zvel() = 0x44444;
} }
static void eelThinkChase(DBloodActor* actor) static void eelThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &eelGoto); aiNewState(actor, &eelGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &eelSearch); aiNewState(actor, &eelSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &eelSearch); aiNewState(actor, &eelSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
int top, bottom; int top, bottom;
GetActorExtents(actor, &top, &bottom); GetActorExtents(actor, &top, &bottom);
int top2, bottom2; int top2, bottom2;
GetSpriteExtents(pTarget, &top2, &bottom2); GetSpriteExtents(pTarget, &top2, &bottom2);
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x399 && top2 > top && abs(nDeltaAngle) < 85) if (nDist < 0x399 && top2 > top && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelSwoop); aiNewState(actor, &eelSwoop);
else if (nDist <= 0x399 && abs(nDeltaAngle) < 85) else if (nDist <= 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelBite); aiNewState(actor, &eelBite);
else if (bottom2 > top && abs(nDeltaAngle) < 85) else if (bottom2 > top && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelSwoop); aiNewState(actor, &eelSwoop);
else if (top2 < top && abs(nDeltaAngle) < 85) else if (top2 < top && abs(nDeltaAngle) < 85)
aiNewState(actor, &eelFly); aiNewState(actor, &eelFly);
} }
} }
return; return;
} }
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
aiNewState(actor, &eelSearch); aiNewState(actor, &eelSearch);
} }
static void eelMoveForward(DBloodActor* actor) static void eelMoveForward(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<26)/120)/120)<<2; int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 26) / 120) / 120) << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
return; return;
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
pSprite->ang = (pSprite->ang+256)&2047; pSprite->ang = (pSprite->ang + 256) & 2047;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= 0x399) if (nDist <= 0x399)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
t1 += nAccel; t1 += nAccel;
else else
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
} }
static void eelMoveSwoop(DBloodActor* actor) static void eelMoveSwoop(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<26)/120)/120)<<2; int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 26) / 120) / 120) << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
return; return;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x8000) && nDist <= 0x399) if (Chance(0x8000) && nDist <= 0x399)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = 0x22222; actor->zvel() = 0x22222;
} }
static void eelMoveAscend(DBloodActor* actor) static void eelMoveAscend(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<26)/120)/120)<<2; int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 26) / 120) / 120) << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
return; return;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x4000) && nDist <= 0x399) if (Chance(0x4000) && nDist <= 0x399)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = -0x8000; actor->zvel() = -0x8000;
} }
void eelMoveToCeil(DBloodActor* actor) void eelMoveToCeil(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = pSprite->z; int z = pSprite->z;
int nSector = pSprite->sectnum; int nSector = pSprite->sectnum;
if (z - pXSprite->targetZ < 0x1000) if (z - pXSprite->targetZ < 0x1000)
{ {
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = 0; pDudeExtraE->active = 0;
pSprite->flags = 0; pSprite->flags = 0;
aiNewState(actor, &eelIdle); aiNewState(actor, &eelIdle);
} }
else else
aiSetTarget(actor, x, y, sector[nSector].ceilingz); aiSetTarget(actor, x, y, sector[nSector].ceilingz);
} }
END_BLD_NS END_BLD_NS

View file

@ -77,197 +77,197 @@ void BurnSeqCallback(int, DBloodActor*)
static void burnThinkSearch(DBloodActor* actor) static void burnThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void burnThinkGoto(DBloodActor* actor) static void burnThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
{ {
switch (pSprite->type) switch (pSprite->type)
{ {
case kDudeBurningCultist: case kDudeBurningCultist:
aiNewState(actor, &cultistBurnSearch); aiNewState(actor, &cultistBurnSearch);
break; break;
case kDudeBurningZombieAxe: case kDudeBurningZombieAxe:
aiNewState(actor, &zombieABurnSearch); aiNewState(actor, &zombieABurnSearch);
break; break;
case kDudeBurningZombieButcher: case kDudeBurningZombieButcher:
aiNewState(actor, &zombieFBurnSearch); aiNewState(actor, &zombieFBurnSearch);
break; break;
case kDudeBurningInnocent: case kDudeBurningInnocent:
aiNewState(actor, &innocentBurnSearch); aiNewState(actor, &innocentBurnSearch);
break; break;
case kDudeBurningBeast: case kDudeBurningBeast:
aiNewState(actor, &beastBurnSearch); aiNewState(actor, &beastBurnSearch);
break; break;
case kDudeBurningTinyCaleb: case kDudeBurningTinyCaleb:
aiNewState(actor, &tinycalebBurnSearch); aiNewState(actor, &tinycalebBurnSearch);
break; break;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(actor, &genDudeBurnSearch); aiNewState(actor, &genDudeBurnSearch);
break; break;
#endif #endif
} }
} }
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void burnThinkChase(DBloodActor* actor) static void burnThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
switch (pSprite->type) switch (pSprite->type)
{ {
case kDudeBurningCultist: case kDudeBurningCultist:
aiNewState(actor, &cultistBurnGoto); aiNewState(actor, &cultistBurnGoto);
break; break;
case kDudeBurningZombieAxe: case kDudeBurningZombieAxe:
aiNewState(actor, &zombieABurnGoto); aiNewState(actor, &zombieABurnGoto);
break; break;
case kDudeBurningZombieButcher: case kDudeBurningZombieButcher:
aiNewState(actor, &zombieFBurnGoto); aiNewState(actor, &zombieFBurnGoto);
break; break;
case kDudeBurningInnocent: case kDudeBurningInnocent:
aiNewState(actor, &innocentBurnGoto); aiNewState(actor, &innocentBurnGoto);
break; break;
case kDudeBurningBeast: case kDudeBurningBeast:
aiNewState(actor, &beastBurnGoto); aiNewState(actor, &beastBurnGoto);
break; break;
case kDudeBurningTinyCaleb: case kDudeBurningTinyCaleb:
aiNewState(actor, &tinycalebBurnGoto); aiNewState(actor, &tinycalebBurnGoto);
break; break;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(actor, &genDudeBurnGoto); aiNewState(actor, &genDudeBurnGoto);
break; break;
#endif #endif
} }
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
switch (pSprite->type) switch (pSprite->type)
{ {
case kDudeBurningCultist: case kDudeBurningCultist:
aiNewState(actor, &cultistBurnSearch); aiNewState(actor, &cultistBurnSearch);
break; break;
case kDudeBurningZombieAxe: case kDudeBurningZombieAxe:
aiNewState(actor, &zombieABurnSearch); aiNewState(actor, &zombieABurnSearch);
break; break;
case kDudeBurningZombieButcher: case kDudeBurningZombieButcher:
aiNewState(actor, &zombieFBurnSearch); aiNewState(actor, &zombieFBurnSearch);
break; break;
case kDudeBurningInnocent: case kDudeBurningInnocent:
aiNewState(actor, &innocentBurnSearch); aiNewState(actor, &innocentBurnSearch);
break; break;
case kDudeBurningBeast: case kDudeBurningBeast:
aiNewState(actor, &beastBurnSearch); aiNewState(actor, &beastBurnSearch);
break; break;
case kDudeBurningTinyCaleb: case kDudeBurningTinyCaleb:
aiNewState(actor, &tinycalebBurnSearch); aiNewState(actor, &tinycalebBurnSearch);
break; break;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(actor, &genDudeBurnSearch); aiNewState(actor, &genDudeBurnSearch);
break; break;
#endif #endif
} }
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x333 && abs(nDeltaAngle) < 85) if (nDist < 0x333 && abs(nDeltaAngle) < 85)
{ {
switch (pSprite->type) switch (pSprite->type)
{ {
case kDudeBurningCultist: case kDudeBurningCultist:
aiNewState(actor, &cultistBurnAttack); aiNewState(actor, &cultistBurnAttack);
break; break;
case kDudeBurningZombieAxe: case kDudeBurningZombieAxe:
aiNewState(actor, &zombieABurnAttack); aiNewState(actor, &zombieABurnAttack);
break; break;
case kDudeBurningZombieButcher: case kDudeBurningZombieButcher:
aiNewState(actor, &zombieFBurnAttack); aiNewState(actor, &zombieFBurnAttack);
break; break;
case kDudeBurningInnocent: case kDudeBurningInnocent:
aiNewState(actor, &innocentBurnAttack); aiNewState(actor, &innocentBurnAttack);
break; break;
case kDudeBurningBeast: case kDudeBurningBeast:
aiNewState(actor, &beastBurnAttack); aiNewState(actor, &beastBurnAttack);
break; break;
case kDudeBurningTinyCaleb: case kDudeBurningTinyCaleb:
aiNewState(actor, &tinycalebBurnAttack); aiNewState(actor, &tinycalebBurnAttack);
break; break;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(actor, &genDudeBurnSearch); aiNewState(actor, &genDudeBurnSearch);
break; break;
#endif #endif
} }
} }
return; return;
} }
} }
} }
switch (pSprite->type) switch (pSprite->type)
{ {
case kDudeBurningCultist: case kDudeBurningCultist:
aiNewState(actor, &cultistBurnGoto); aiNewState(actor, &cultistBurnGoto);
break; break;
case kDudeBurningZombieAxe: case kDudeBurningZombieAxe:
aiNewState(actor, &zombieABurnGoto); aiNewState(actor, &zombieABurnGoto);
break; break;
case 242: case 242:
aiNewState(actor, &zombieFBurnGoto); aiNewState(actor, &zombieFBurnGoto);
break; break;
case kDudeBurningInnocent: case kDudeBurningInnocent:
aiNewState(actor, &innocentBurnGoto); aiNewState(actor, &innocentBurnGoto);
break; break;
case kDudeBurningBeast: case kDudeBurningBeast:
aiNewState(actor, &beastBurnGoto); aiNewState(actor, &beastBurnGoto);
break; break;
case kDudeBurningTinyCaleb: case kDudeBurningTinyCaleb:
aiNewState(actor, &tinycalebBurnGoto); aiNewState(actor, &tinycalebBurnGoto);
break; break;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(actor, &genDudeBurnSearch); aiNewState(actor, &genDudeBurnSearch);
break; break;
#endif #endif
} }
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,14 +30,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void calebThinkSearch(DBloodActor *); static void calebThinkSearch(DBloodActor*);
static void calebThinkGoto(DBloodActor *); static void calebThinkGoto(DBloodActor*);
static void calebThinkChase(DBloodActor *); static void calebThinkChase(DBloodActor*);
static void calebThinkSwimGoto(DBloodActor *); static void calebThinkSwimGoto(DBloodActor*);
static void calebThinkSwimChase(DBloodActor *); static void calebThinkSwimChase(DBloodActor*);
static void sub_65D04(DBloodActor *); static void sub_65D04(DBloodActor*);
static void sub_65F44(DBloodActor *); static void sub_65F44(DBloodActor*);
static void sub_661E0(DBloodActor *); static void sub_661E0(DBloodActor*);
AISTATE tinycalebIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE tinycalebIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
AISTATE tinycalebChase = { kAiStateChase, 6, -1, 0, NULL, aiMoveForward, calebThinkChase, NULL }; AISTATE tinycalebChase = { kAiStateChase, 6, -1, 0, NULL, aiMoveForward, calebThinkChase, NULL };
@ -60,364 +60,364 @@ AISTATE tinycaleb139698 = { kAiStateOther, 8, -1, 120, NULL, aiMoveTurn, NULL, &
void SeqAttackCallback(int, DBloodActor* actor) void SeqAttackCallback(int, DBloodActor* actor)
{ {
spritetype *pSprite = &actor->s(); spritetype* pSprite = &actor->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
int dz = actor->dudeSlope; int dz = actor->dudeSlope;
dx += Random2(1500); dx += Random2(1500);
dy += Random2(1500); dy += Random2(1500);
dz += Random2(1500); dz += Random2(1500);
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
int r1 = Random3(500); int r1 = Random3(500);
int r2 = Random3(1000); int r2 = Random3(1000);
int r3 = Random3(1000); int r3 = Random3(1000);
actFireVector(actor, 0, 0, dx+r3, dy+r2, dz+r1, kVectorShell); actFireVector(actor, 0, 0, dx + r3, dy + r2, dz + r1, kVectorShell);
} }
if (Chance(0x8000)) if (Chance(0x8000))
sfxPlay3DSound(actor, 10000+Random(5), -1, 0); sfxPlay3DSound(actor, 10000 + Random(5), -1, 0);
if (Chance(0x8000)) if (Chance(0x8000))
sfxPlay3DSound(actor, 1001, -1, 0); sfxPlay3DSound(actor, 1001, -1, 0);
else else
sfxPlay3DSound(actor, 1002, -1, 0); sfxPlay3DSound(actor, 1002, -1, 0);
} }
static void calebThinkSearch(DBloodActor* actor) static void calebThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void calebThinkGoto(DBloodActor* actor) static void calebThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
{ {
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimSearch); aiNewState(actor, &tinycalebSwimSearch);
else else
aiNewState(actor, &tinycalebSearch); aiNewState(actor, &tinycalebSearch);
} }
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void calebThinkChase(DBloodActor* actor) static void calebThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimSearch); aiNewState(actor, &tinycalebSwimSearch);
else else
aiNewState(actor, &tinycalebSearch); aiNewState(actor, &tinycalebSearch);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimSearch); aiNewState(actor, &tinycalebSwimSearch);
else else
{ {
aiPlay3DSound(actor, 11000+Random(4), AI_SFX_PRIORITY_1, -1); aiPlay3DSound(actor, 11000 + Random(4), AI_SFX_PRIORITY_1, -1);
aiNewState(actor, &tinycalebSearch); aiNewState(actor, &tinycalebSearch);
} }
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimSearch); aiNewState(actor, &tinycalebSwimSearch);
else else
aiNewState(actor, &tinycalebSearch); aiNewState(actor, &tinycalebSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
actor->dudeSlope = DivScale(pTarget->z-pSprite->z, nDist, 10); actor->dudeSlope = DivScale(pTarget->z - pSprite->z, nDist, 10);
if (nDist < 0x599 && abs(nDeltaAngle) < 28) if (nDist < 0x599 && abs(nDeltaAngle) < 28)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
switch (hit) switch (hit)
{ {
case -1: case -1:
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimAttack); aiNewState(actor, &tinycalebSwimAttack);
else else
aiNewState(actor, &tinycalebAttack); aiNewState(actor, &tinycalebAttack);
break; break;
case 3: case 3:
if (pSprite->type != gHitInfo.hitactor->s().type) if (pSprite->type != gHitInfo.hitactor->s().type)
{ {
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimAttack); aiNewState(actor, &tinycalebSwimAttack);
else else
aiNewState(actor, &tinycalebAttack); aiNewState(actor, &tinycalebAttack);
} }
else else
{ {
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimDodge); aiNewState(actor, &tinycalebSwimDodge);
else else
aiNewState(actor, &tinycalebDodge); aiNewState(actor, &tinycalebDodge);
} }
break; break;
default: default:
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimAttack); aiNewState(actor, &tinycalebSwimAttack);
else else
aiNewState(actor, &tinycalebAttack); aiNewState(actor, &tinycalebAttack);
break; break;
} }
} }
} }
return; return;
} }
} }
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &tinycalebSwimGoto); aiNewState(actor, &tinycalebSwimGoto);
else else
aiNewState(actor, &tinycalebGoto); aiNewState(actor, &tinycalebGoto);
if (Chance(0x2000)) if (Chance(0x2000))
sfxPlay3DSound(actor, 10000 + Random(5), -1, 0); sfxPlay3DSound(actor, 10000 + Random(5), -1, 0);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void calebThinkSwimGoto(DBloodActor* actor) static void calebThinkSwimGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &tinycalebSwimSearch); aiNewState(actor, &tinycalebSwimSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void calebThinkSwimChase(DBloodActor* actor) static void calebThinkSwimChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &tinycalebSwimGoto); aiNewState(actor, &tinycalebSwimGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &tinycalebSwimSearch); aiNewState(actor, &tinycalebSwimSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &tinycalebSwimSearch); aiNewState(actor, &tinycalebSwimSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = pDudeInfo->eyeHeight+pSprite->z; int height = pDudeInfo->eyeHeight + pSprite->z;
int top, bottom; int top, bottom;
GetActorExtents(actor, &top, &bottom); GetActorExtents(actor, &top, &bottom);
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x400 && abs(nDeltaAngle) < 85) if (nDist < 0x400 && abs(nDeltaAngle) < 85)
aiNewState(actor, &tinycalebSwimAttack); aiNewState(actor, &tinycalebSwimAttack);
else else
aiNewState(actor, &tinycaleb13967C); aiNewState(actor, &tinycaleb13967C);
} }
} }
return; return;
} }
aiNewState(actor, &tinycalebSwimGoto); aiNewState(actor, &tinycalebSwimGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void sub_65D04(DBloodActor* actor) static void sub_65D04(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = pDudeInfo->frontSpeed<<2; int nAccel = pDudeInfo->frontSpeed << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
return; return;
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
pSprite->ang = (pSprite->ang+256)&2047; pSprite->ang = (pSprite->ang + 256) & 2047;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Random(64) < 32 && nDist <= 0x400) if (Random(64) < 32 && nDist <= 0x400)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
t1 += nAccel; t1 += nAccel;
else else
t1 += nAccel>>2; t1 += nAccel >> 2;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
} }
static void sub_65F44(DBloodActor* actor) static void sub_65F44(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight; int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight; int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = pDudeInfo->frontSpeed<<2; int nAccel = pDudeInfo->frontSpeed << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
{ {
pXSprite->goalAng = (pSprite->ang+512)&2047; pXSprite->goalAng = (pSprite->ang + 512) & 2047;
return; return;
} }
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int dz = z2 - z; int dz = z2 - z;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x600) && nDist <= 0x400) if (Chance(0x600) && nDist <= 0x400)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel; t1 += nAccel;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = -dz; actor->zvel() = -dz;
} }
static void sub_661E0(DBloodActor* actor) static void sub_661E0(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight; int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight; int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = pDudeInfo->frontSpeed<<2; int nAccel = pDudeInfo->frontSpeed << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
{ {
pSprite->ang = (pSprite->ang+512)&2047; pSprite->ang = (pSprite->ang + 512) & 2047;
return; return;
} }
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int dz = (z2 - z)<<3; int dz = (z2 - z) << 3;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x4000) && nDist <= 0x400) if (Chance(0x4000) && nDist <= 0x400)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = dz; actor->zvel() = dz;
} }
END_BLD_NS END_BLD_NS

View file

@ -30,10 +30,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void cerberusThinkSearch(DBloodActor *actor); static void cerberusThinkSearch(DBloodActor* actor);
static void cerberusThinkTarget(DBloodActor *actor); static void cerberusThinkTarget(DBloodActor* actor);
static void cerberusThinkGoto(DBloodActor *actor); static void cerberusThinkGoto(DBloodActor* actor);
static void cerberusThinkChase(DBloodActor *actor); static void cerberusThinkChase(DBloodActor* actor);
AISTATE cerberusIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, cerberusThinkTarget, NULL }; AISTATE cerberusIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, cerberusThinkTarget, NULL };
@ -58,422 +58,422 @@ AISTATE cerberus1398AC = { kAiStateOther, 7, -1, 120, NULL, aiMoveTurn, NULL, &c
void cerberusBiteSeqCallback(int, DBloodActor* actor) void cerberusBiteSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype *pSprite = &actor->s(); spritetype* pSprite = &actor->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int dz = pTarget->z-pSprite->z; int dz = pTarget->z - pSprite->z;
actFireVector(actor, 350, -100, dx, dy, dz, kVectorCerberusHack); actFireVector(actor, 350, -100, dx, dy, dz, kVectorCerberusHack);
actFireVector(actor, -350, 0, dx, dy, dz, kVectorCerberusHack); actFireVector(actor, -350, 0, dx, dy, dz, kVectorCerberusHack);
actFireVector(actor, 0, 0, dx, dy, dz, kVectorCerberusHack); actFireVector(actor, 0, 0, dx, dy, dz, kVectorCerberusHack);
} }
void cerberusBurnSeqCallback(int, DBloodActor* actor) void cerberusBurnSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int height = pDudeInfo->eyeHeight*pSprite->yrepeat; int height = pDudeInfo->eyeHeight * pSprite->yrepeat;
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = height; // ??? int z = height; // ???
TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa }; TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa };
Aim aim; Aim aim;
aim.dx = CosScale16(pSprite->ang); aim.dx = CosScale16(pSprite->ang);
aim.dy = SinScale16(pSprite->ang); aim.dy = SinScale16(pSprite->ang);
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
BloodStatIterator it(kStatDude); BloodStatIterator it(kStatDude);
while (auto actor2 = it.Next()) while (auto actor2 = it.Next())
{ {
spritetype *pSprite2 = &actor2->s(); spritetype* pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags & 8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
int y2 = pSprite2->y; int y2 = pSprite2->y;
int z2 = pSprite2->z; int z2 = pSprite2->z;
int nDist = approxDist(x2-x, y2-y); int nDist = approxDist(x2 - x, y2 - y);
if (nDist == 0 || nDist > 0x2800) if (nDist == 0 || nDist > 0x2800)
continue; continue;
if (tt1.at10) if (tt1.at10)
{ {
int t = DivScale(nDist, tt1.at10, 12); int t = DivScale(nDist, tt1.at10, 12);
x2 += (actor2->xvel() * t) >> 12; x2 += (actor2->xvel() * t) >> 12;
y2 += (actor2->yvel() * t) >> 12; y2 += (actor2->yvel() * t) >> 12;
z2 += (actor2->zvel() * t) >> 8; z2 += (actor2->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
int tz = z+MulScale(actor->dudeSlope, nDist, 10); int tz = z + MulScale(actor->dudeSlope, nDist, 10);
int tsr = MulScale(9460, nDist, 10); int tsr = MulScale(9460, nDist, 10);
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite2, &top, &bottom); GetSpriteExtents(pSprite2, &top, &bottom);
if (tz-tsr > bottom || tz+tsr < top) if (tz - tsr > bottom || tz + tsr < top)
continue; continue;
int dx = (tx-x2)>>4; int dx = (tx - x2) >> 4;
int dy = (ty-y2)>>4; int dy = (ty - y2) >> 4;
int dz = (tz-z2)>>8; int dz = (tz - z2) >> 8;
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz); int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
if (nDist2 < nClosest) if (nDist2 < nClosest)
{ {
int nAngle = getangle(x2-x, y2-y); int nAngle = getangle(x2 - x, y2 - y);
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024; int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
if (abs(nDeltaAngle) <= tt1.at8) if (abs(nDeltaAngle) <= tt1.at8)
{ {
int tz = pSprite2->z-pSprite->z; int tz = pSprite2->z - pSprite->z;
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum)) if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
{ {
nClosest = nDist2; nClosest = nDist2;
aim.dx = CosScale16(nAngle); aim.dx = CosScale16(nAngle);
aim.dy = SinScale16(nAngle); aim.dy = SinScale16(nAngle);
aim.dz = DivScale(tz, nDist, 10); aim.dz = DivScale(tz, nDist, 10);
} }
else else
aim.dz = tz; aim.dz = tz;
} }
} }
} }
switch (pSprite->type) { switch (pSprite->type) {
case kDudeCerberusTwoHead: case kDudeCerberusTwoHead:
actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus); actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus); actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
break; break;
case kDudeCerberusOneHead: case kDudeCerberusOneHead:
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus); actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
break; break;
} }
} }
void cerberusBurnSeqCallback2(int, DBloodActor* actor) void cerberusBurnSeqCallback2(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int height = pDudeInfo->eyeHeight*pSprite->yrepeat; int height = pDudeInfo->eyeHeight * pSprite->yrepeat;
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = height; // ??? int z = height; // ???
TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa }; TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa };
Aim aim; Aim aim;
int ax, ay, az; int ax, ay, az;
aim.dx = ax = CosScale16(pSprite->ang); aim.dx = ax = CosScale16(pSprite->ang);
aim.dy = ay = SinScale16(pSprite->ang); aim.dy = ay = SinScale16(pSprite->ang);
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
az = 0; az = 0;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
BloodStatIterator it(kStatDude); BloodStatIterator it(kStatDude);
while (auto actor2 = it.Next()) while (auto actor2 = it.Next())
{ {
spritetype *pSprite2 = &actor2->s(); spritetype* pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags & 8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
int y2 = pSprite2->y; int y2 = pSprite2->y;
int z2 = pSprite2->z; int z2 = pSprite2->z;
int nDist = approxDist(x2-x, y2-y); int nDist = approxDist(x2 - x, y2 - y);
if (nDist == 0 || nDist > 0x2800) if (nDist == 0 || nDist > 0x2800)
continue; continue;
if (tt1.at10) if (tt1.at10)
{ {
int t = DivScale(nDist, tt1.at10, 12); int t = DivScale(nDist, tt1.at10, 12);
x2 += (actor->xvel() * t) >> 12; x2 += (actor->xvel() * t) >> 12;
y2 += (actor->yvel() * t) >> 12; y2 += (actor->yvel() * t) >> 12;
z2 += (actor->zvel() * t) >> 8; z2 += (actor->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
int tz = z+MulScale(actor->dudeSlope, nDist, 10); int tz = z + MulScale(actor->dudeSlope, nDist, 10);
int tsr = MulScale(9460, nDist, 10); int tsr = MulScale(9460, nDist, 10);
int top, bottom; int top, bottom;
GetActorExtents(actor2, &top, &bottom); GetActorExtents(actor2, &top, &bottom);
if (tz-tsr > bottom || tz+tsr < top) if (tz - tsr > bottom || tz + tsr < top)
continue; continue;
int dx = (tx-x2)>>4; int dx = (tx - x2) >> 4;
int dy = (ty-y2)>>4; int dy = (ty - y2) >> 4;
int dz = (tz-z2)>>8; int dz = (tz - z2) >> 8;
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz); int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
if (nDist2 < nClosest) if (nDist2 < nClosest)
{ {
int nAngle = getangle(x2-x, y2-y); int nAngle = getangle(x2 - x, y2 - y);
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024; int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
if (abs(nDeltaAngle) <= tt1.at8) if (abs(nDeltaAngle) <= tt1.at8)
{ {
DUDEINFO *pDudeInfo2 = getDudeInfo(pSprite2->type); DUDEINFO* pDudeInfo2 = getDudeInfo(pSprite2->type);
int height = (pDudeInfo2->aimHeight*pSprite2->yrepeat)<<2; int height = (pDudeInfo2->aimHeight * pSprite2->yrepeat) << 2;
int tz = (z2-height)-z; int tz = (z2 - height) - z;
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum)) if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
{ {
nClosest = nDist2; nClosest = nDist2;
aim.dx = CosScale16(nAngle); aim.dx = CosScale16(nAngle);
aim.dy = SinScale16(nAngle); aim.dy = SinScale16(nAngle);
aim.dz = DivScale(tz, nDist, 10); aim.dz = DivScale(tz, nDist, 10);
} }
else else
aim.dz = tz; aim.dz = tz;
} }
} }
} }
switch (pSprite->type) { switch (pSprite->type) {
case kDudeCerberusTwoHead: case kDudeCerberusTwoHead:
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound); actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFlameHound); actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFlameHound);
break; break;
case kDudeCerberusOneHead: case kDudeCerberusOneHead:
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound); actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
break; break;
} }
} }
static void cerberusThinkSearch(DBloodActor* actor) static void cerberusThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void cerberusThinkTarget(DBloodActor* actor) static void cerberusThinkTarget(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10) if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++; pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D* pTarget = &actor->basePoint(); POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
if (pSprite->type == kDudeCerberusTwoHead) if (pSprite->type == kDudeCerberusTwoHead)
aiNewState(actor, &cerberus139890); aiNewState(actor, &cerberus139890);
else else
aiNewState(actor, &cerberus1398AC); aiNewState(actor, &cerberus1398AC);
return; return;
} }
if (Chance(pDudeInfo->alertChance)) if (Chance(pDudeInfo->alertChance))
{ {
for (int p = connecthead; p >= 0; p = connectpoint2[p]) for (int p = connecthead; p >= 0; p = connectpoint2[p])
{ {
PLAYER *pPlayer = &gPlayer[p]; PLAYER* pPlayer = &gPlayer[p];
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0) if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
continue; continue;
int x = pPlayer->pSprite->x; int x = pPlayer->pSprite->x;
int y = pPlayer->pSprite->y; int y = pPlayer->pSprite->y;
int z = pPlayer->pSprite->z; int z = pPlayer->pSprite->z;
int nSector = pPlayer->pSprite->sectnum; int nSector = pPlayer->pSprite->sectnum;
int dx = x-pSprite->x; int dx = x - pSprite->x;
int dy = y-pSprite->y; int dy = y - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist) if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
continue; continue;
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum)) if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
continue; continue;
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
aiSetTarget(actor, pPlayer->actor()); aiSetTarget(actor, pPlayer->actor());
aiActivateDude(actor); aiActivateDude(actor);
} }
else if (nDist < pDudeInfo->hearDist) else if (nDist < pDudeInfo->hearDist)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
aiSetTarget(actor, x, y, z); aiSetTarget(actor, x, y, z);
aiActivateDude(actor); aiActivateDude(actor);
} }
else else
continue; continue;
break; break;
} }
} }
} }
static void cerberusThinkGoto(DBloodActor* actor) static void cerberusThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
{ {
switch (pSprite->type) { switch (pSprite->type) {
case kDudeCerberusTwoHead: case kDudeCerberusTwoHead:
aiNewState(actor, &cerberusSearch); aiNewState(actor, &cerberusSearch);
break; break;
case kDudeCerberusOneHead: case kDudeCerberusOneHead:
aiNewState(actor, &cerberus2Search); aiNewState(actor, &cerberus2Search);
break; break;
} }
} }
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void cerberusThinkChase(DBloodActor* actor) static void cerberusThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) { if (actor->GetTarget() == nullptr) {
switch (pSprite->type) { switch (pSprite->type) {
case kDudeCerberusTwoHead: case kDudeCerberusTwoHead:
aiNewState(actor, &cerberusGoto); aiNewState(actor, &cerberusGoto);
break; break;
case kDudeCerberusOneHead: case kDudeCerberusOneHead:
aiNewState(actor, &cerberus2Goto); aiNewState(actor, &cerberus2Goto);
break; break;
} }
return; return;
} }
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return;
}
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return;
}
if (!actor->ValidateTarget(__FUNCTION__)) return; DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x;
int dy = pTarget->y-pSprite->y;
aiChooseDirection(actor,getangle(dx, dy));
if (pXTarget->health == 0) {
switch (pSprite->type) {
case kDudeCerberusTwoHead:
aiNewState(actor, &cerberusSearch);
break;
case kDudeCerberusOneHead:
aiNewState(actor, &cerberus2Search);
break;
}
return;
}
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) { if (!actor->ValidateTarget(__FUNCTION__)) return;
switch (pSprite->type) { spritetype* pTarget = &actor->GetTarget()->s();
case kDudeCerberusTwoHead: XSPRITE* pXTarget = &actor->GetTarget()->x();
aiNewState(actor, &cerberusSearch); int dx = pTarget->x - pSprite->x;
break; int dy = pTarget->y - pSprite->y;
case kDudeCerberusOneHead: aiChooseDirection(actor, getangle(dx, dy));
aiNewState(actor, &cerberus2Search);
break;
}
return;
}
int nDist = approxDist(dx, dy); if (pXTarget->health == 0) {
if (nDist <= pDudeInfo->seeDist) switch (pSprite->type) {
{ case kDudeCerberusTwoHead:
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; aiNewState(actor, &cerberusSearch);
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; break;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) case kDudeCerberusOneHead:
{ aiNewState(actor, &cerberus2Search);
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) { break;
aiSetTarget(actor, actor->GetTarget()); }
return;
if (nDist < 0x1b00 && nDist > 0xd00 && abs(nDeltaAngle) < 85) { }
switch (pSprite->type) {
case kDudeCerberusTwoHead:
aiNewState(actor, &cerberusBurn);
break;
case kDudeCerberusOneHead:
aiNewState(actor, &cerberus2Burn);
break;
}
}
else if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85) { if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0) {
switch (pSprite->type) { switch (pSprite->type) {
case kDudeCerberusTwoHead: case kDudeCerberusTwoHead:
aiNewState(actor, &cerberus3Burn); aiNewState(actor, &cerberusSearch);
break; break;
case kDudeCerberusOneHead: case kDudeCerberusOneHead:
aiNewState(actor, &cerberus4Burn); aiNewState(actor, &cerberus2Search);
break; break;
} }
} return;
else if (nDist < 0x200 && abs(nDeltaAngle) < 85) }
{
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
switch (pSprite->type) {
case kDudeCerberusTwoHead:
switch (hit) {
case -1:
aiNewState(actor, &cerberusBite);
break;
case 3:
if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeHellHound)
aiNewState(actor, &cerberusBite);
break;
case 0:
case 4:
break;
default:
aiNewState(actor, &cerberusBite);
break;
}
break;
case kDudeCerberusOneHead:
switch (hit) {
case -1:
aiNewState(actor, &cerberus2Bite);
break;
case 3:
if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeHellHound)
aiNewState(actor, &cerberus2Bite);
break;
case 0:
case 4:
break;
default:
aiNewState(actor, &cerberus2Bite);
break;
}
break;
}
}
return;
}
}
}
switch (pSprite->type) { int nDist = approxDist(dx, dy);
case kDudeCerberusTwoHead: if (nDist <= pDudeInfo->seeDist)
aiNewState(actor, &cerberusGoto); {
break; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
case kDudeCerberusOneHead: int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
aiNewState(actor, &cerberus2Goto); if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
break; {
} if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) {
actor->SetTarget(nullptr); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x1b00 && nDist > 0xd00 && abs(nDeltaAngle) < 85) {
switch (pSprite->type) {
case kDudeCerberusTwoHead:
aiNewState(actor, &cerberusBurn);
break;
case kDudeCerberusOneHead:
aiNewState(actor, &cerberus2Burn);
break;
}
}
else if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85) {
switch (pSprite->type) {
case kDudeCerberusTwoHead:
aiNewState(actor, &cerberus3Burn);
break;
case kDudeCerberusOneHead:
aiNewState(actor, &cerberus4Burn);
break;
}
}
else if (nDist < 0x200 && abs(nDeltaAngle) < 85)
{
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
switch (pSprite->type) {
case kDudeCerberusTwoHead:
switch (hit) {
case -1:
aiNewState(actor, &cerberusBite);
break;
case 3:
if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeHellHound)
aiNewState(actor, &cerberusBite);
break;
case 0:
case 4:
break;
default:
aiNewState(actor, &cerberusBite);
break;
}
break;
case kDudeCerberusOneHead:
switch (hit) {
case -1:
aiNewState(actor, &cerberus2Bite);
break;
case 3:
if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeHellHound)
aiNewState(actor, &cerberus2Bite);
break;
case 0:
case 4:
break;
default:
aiNewState(actor, &cerberus2Bite);
break;
}
break;
}
}
return;
}
}
}
switch (pSprite->type) {
case kDudeCerberusTwoHead:
aiNewState(actor, &cerberusGoto);
break;
case kDudeCerberusOneHead:
aiNewState(actor, &cerberus2Goto);
break;
}
actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -30,14 +30,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void gillThinkSearch(DBloodActor *); static void gillThinkSearch(DBloodActor*);
static void gillThinkGoto(DBloodActor *); static void gillThinkGoto(DBloodActor*);
static void gillThinkChase(DBloodActor *); static void gillThinkChase(DBloodActor*);
static void gillThinkSwimGoto(DBloodActor *); static void gillThinkSwimGoto(DBloodActor*);
static void gillThinkSwimChase(DBloodActor *); static void gillThinkSwimChase(DBloodActor*);
static void sub_6CB00(DBloodActor *); static void sub_6CB00(DBloodActor*);
static void sub_6CD74(DBloodActor *); static void sub_6CD74(DBloodActor*);
static void sub_6D03C(DBloodActor *); static void sub_6D03C(DBloodActor*);
AISTATE gillBeastIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE gillBeastIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
@ -60,358 +60,358 @@ AISTATE gillBeast13A170 = { kAiStateOther, 10, -1, 120, NULL, NULL, aiMoveTurn,
void GillBiteSeqCallback(int, DBloodActor* actor) void GillBiteSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
int dz = pSprite->z-pTarget->z; int dz = pSprite->z - pTarget->z;
dx += Random3(2000); dx += Random3(2000);
dy += Random3(2000); dy += Random3(2000);
actFireVector(actor, 0, 0, dx, dy, dz, kVectorGillBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorGillBite);
actFireVector(actor, 0, 0, dx, dy, dz, kVectorGillBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorGillBite);
actFireVector(actor, 0, 0, dx, dy, dz, kVectorGillBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorGillBite);
} }
static void gillThinkSearch(DBloodActor* actor) static void gillThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void gillThinkGoto(DBloodActor* actor) static void gillThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
{ {
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
else else
aiNewState(actor, &gillBeastSearch); aiNewState(actor, &gillBeastSearch);
} }
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void gillThinkChase(DBloodActor* actor) static void gillThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
else else
aiNewState(actor, &gillBeastSearch); aiNewState(actor, &gillBeastSearch);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
else else
aiNewState(actor, &gillBeastSearch); aiNewState(actor, &gillBeastSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
else else
aiNewState(actor, &gillBeastSearch); aiNewState(actor, &gillBeastSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
actor->dudeSlope = DivScale(pTarget->z-pSprite->z, nDist, 10); actor->dudeSlope = DivScale(pTarget->z - pSprite->z, nDist, 10);
if (nDist < 921 && abs(nDeltaAngle) < 28) if (nDist < 921 && abs(nDeltaAngle) < 28)
{ {
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
switch (hit) switch (hit)
{ {
case -1: case -1:
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimBite); aiNewState(actor, &gillBeastSwimBite);
else else
aiNewState(actor, &gillBeastBite); aiNewState(actor, &gillBeastBite);
break; break;
case 3: case 3:
if (pSprite->type != gHitInfo.hitactor->s().type) if (pSprite->type != gHitInfo.hitactor->s().type)
{ {
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimBite); aiNewState(actor, &gillBeastSwimBite);
else else
aiNewState(actor, &gillBeastBite); aiNewState(actor, &gillBeastBite);
} }
else else
{ {
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimDodge); aiNewState(actor, &gillBeastSwimDodge);
else else
aiNewState(actor, &gillBeastDodge); aiNewState(actor, &gillBeastDodge);
} }
break; break;
default: default:
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimBite); aiNewState(actor, &gillBeastSwimBite);
else else
aiNewState(actor, &gillBeastBite); aiNewState(actor, &gillBeastBite);
break; break;
} }
} }
} }
return; return;
} }
} }
XSECTOR *pXSector; XSECTOR* pXSector;
int nXSector = sector[pSprite->sectnum].extra; int nXSector = sector[pSprite->sectnum].extra;
if (nXSector > 0) if (nXSector > 0)
pXSector = &xsector[nXSector]; pXSector = &xsector[nXSector];
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater)
aiNewState(actor, &gillBeastSwimGoto); aiNewState(actor, &gillBeastSwimGoto);
else else
aiNewState(actor, &gillBeastGoto); aiNewState(actor, &gillBeastGoto);
sfxPlay3DSound(actor, 1701, -1, 0); sfxPlay3DSound(actor, 1701, -1, 0);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void gillThinkSwimGoto(DBloodActor* actor) static void gillThinkSwimGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void gillThinkSwimChase(DBloodActor* actor) static void gillThinkSwimChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &gillBeastSwimSearch); aiNewState(actor, &gillBeastSwimSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = pDudeInfo->eyeHeight+pSprite->z; int height = pDudeInfo->eyeHeight + pSprite->z;
int top, bottom; int top, bottom;
GetActorExtents(actor, &top, &bottom); GetActorExtents(actor, &top, &bottom);
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x400 && abs(nDeltaAngle) < 85) if (nDist < 0x400 && abs(nDeltaAngle) < 85)
aiNewState(actor, &gillBeastSwimBite); aiNewState(actor, &gillBeastSwimBite);
else else
{ {
aiPlay3DSound(actor, 1700, AI_SFX_PRIORITY_1, -1); aiPlay3DSound(actor, 1700, AI_SFX_PRIORITY_1, -1);
aiNewState(actor, &gillBeast13A154); aiNewState(actor, &gillBeast13A154);
} }
} }
} }
else else
aiNewState(actor, &gillBeast13A154); aiNewState(actor, &gillBeast13A154);
return; return;
} }
aiNewState(actor, &gillBeastSwimGoto); aiNewState(actor, &gillBeastSwimGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void sub_6CB00(DBloodActor* actor) static void sub_6CB00(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
int nSprite = pSprite->index; int nSprite = pSprite->index;
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<27)/120)/120)<<2; int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 27) / 120) / 120) << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
return; return;
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
pSprite->ang = (pSprite->ang+256)&2047; pSprite->ang = (pSprite->ang + 256) & 2047;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Random(64) < 32 && nDist <= 0x400) if (Random(64) < 32 && nDist <= 0x400)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
t1 += nAccel; t1 += nAccel;
else else
t1 += nAccel>>2; t1 += nAccel >> 2;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
} }
static void sub_6CD74(DBloodActor* actor) static void sub_6CD74(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight; int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight; int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<27)/120)/120)<<2; int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 27) / 120) / 120) << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
{ {
pXSprite->goalAng = (pSprite->ang+512)&2047; pXSprite->goalAng = (pSprite->ang + 512) & 2047;
return; return;
} }
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int dz = z2 - z; int dz = z2 - z;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x600) && nDist <= 0x400) if (Chance(0x600) && nDist <= 0x400)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel; t1 += nAccel;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = -dz; actor->zvel() = -dz;
} }
static void sub_6D03C(DBloodActor* actor) static void sub_6D03C(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight; int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight; int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024; int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4; int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047; pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<27)/120)/120)<<2; int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 27) / 120) / 120) << 2;
if (abs(nAng) > 341) if (abs(nAng) > 341)
{ {
pSprite->ang = (pSprite->ang+512)&2047; pSprite->ang = (pSprite->ang + 512) & 2047;
return; return;
} }
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int dz = (z2 - z)<<3; int dz = (z2 - z) << 3;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (Chance(0x4000) && nDist <= 0x400) if (Chance(0x4000) && nDist <= 0x400)
return; return;
int nCos = Cos(pSprite->ang); int nCos = Cos(pSprite->ang);
int nSin = Sin(pSprite->ang); int nSin = Sin(pSprite->ang);
int vx = actor->xvel(); int vx = actor->xvel();
int vy = actor->yvel(); int vy = actor->yvel();
int t1 = DMulScale(vx, nCos, vy, nSin, 30); int t1 = DMulScale(vx, nCos, vy, nSin, 30);
int t2 = DMulScale(vx, nSin, -vy, nCos, 30); int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
t1 += nAccel>>1; t1 += nAccel >> 1;
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
actor->zvel() = dz; actor->zvel() = dz;
} }
END_BLD_NS END_BLD_NS

View file

@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void handThinkSearch(DBloodActor *); static void handThinkSearch(DBloodActor*);
static void handThinkGoto(DBloodActor *); static void handThinkGoto(DBloodActor*);
static void handThinkChase(DBloodActor *); static void handThinkChase(DBloodActor*);
AISTATE handIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE handIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
AISTATE hand13A3B4 = { kAiStateOther, 0, -1, 0, NULL, NULL, NULL, NULL }; AISTATE hand13A3B4 = { kAiStateOther, 0, -1, 0, NULL, NULL, NULL, NULL };
@ -44,91 +44,91 @@ AISTATE handJump = { kAiStateChase, 7, nJumpClient, 120, NULL, NULL, NULL, &hand
void HandJumpSeqCallback(int, DBloodActor* actor) void HandJumpSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
if (IsPlayerSprite(pTarget)) if (IsPlayerSprite(pTarget))
{ {
PLAYER *pPlayer = &gPlayer[pTarget->type-kDudePlayer1]; PLAYER* pPlayer = &gPlayer[pTarget->type - kDudePlayer1];
if (!pPlayer->hand) if (!pPlayer->hand)
{ {
pPlayer->hand = 1; pPlayer->hand = 1;
actPostSprite(actor, kStatFree); actPostSprite(actor, kStatFree);
} }
} }
} }
static void handThinkSearch(DBloodActor* actor) static void handThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void handThinkGoto(DBloodActor* actor) static void handThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &handSearch); aiNewState(actor, &handSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void handThinkChase(DBloodActor* actor) static void handThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &handGoto); aiNewState(actor, &handGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &handSearch); aiNewState(actor, &handSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &handSearch); aiNewState(actor, &handSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x233 && abs(nDeltaAngle) < 85 && gGameOptions.nGameType == 0) if (nDist < 0x233 && abs(nDeltaAngle) < 85 && gGameOptions.nGameType == 0)
aiNewState(actor, &handJump); aiNewState(actor, &handJump);
return; return;
} }
} }
} }
aiNewState(actor, &handGoto); aiNewState(actor, &handGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void houndThinkSearch(DBloodActor *); static void houndThinkSearch(DBloodActor*);
static void houndThinkGoto(DBloodActor *); static void houndThinkGoto(DBloodActor*);
static void houndThinkChase(DBloodActor *); static void houndThinkChase(DBloodActor*);
AISTATE houndIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE houndIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
AISTATE houndSearch = { kAiStateMove, 8, -1, 1800, NULL, aiMoveForward, houndThinkSearch, &houndIdle }; AISTATE houndSearch = { kAiStateMove, 8, -1, 1800, NULL, aiMoveForward, houndThinkSearch, &houndIdle };
@ -45,113 +45,113 @@ AISTATE houndBurn = { kAiStateChase, 7, nHoundBurnClient, 60, NULL, NULL, NULL,
void houndBiteSeqCallback(int, DBloodActor* actor) void houndBiteSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
if (IsPlayerSprite(pTarget) || gModernMap) // allow to hit non-player targets if (IsPlayerSprite(pTarget) || gModernMap) // allow to hit non-player targets
actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite); actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite);
#else #else
if (IsPlayerSprite(pTarget)) if (IsPlayerSprite(pTarget))
actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite); actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite);
#endif #endif
} }
void houndBurnSeqCallback(int, DBloodActor* actor) void houndBurnSeqCallback(int, DBloodActor* actor)
{ {
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
actFireMissile(pSprite, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFlameHound); actFireMissile(pSprite, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFlameHound);
} }
static void houndThinkSearch(DBloodActor* actor) static void houndThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void houndThinkGoto(DBloodActor* actor) static void houndThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &houndSearch); aiNewState(actor, &houndSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void houndThinkChase(DBloodActor* actor) static void houndThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &houndGoto); aiNewState(actor, &houndGoto);
return; return;
} }
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &houndSearch); aiNewState(actor, &houndSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &houndSearch); aiNewState(actor, &houndSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85) if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85)
aiNewState(actor, &houndBurn); aiNewState(actor, &houndBurn);
else if(nDist < 0x266 && abs(nDeltaAngle) < 85) else if (nDist < 0x266 && abs(nDeltaAngle) < 85)
aiNewState(actor, &houndBite); aiNewState(actor, &houndBite);
return; return;
} }
} }
} }
aiNewState(actor, &houndGoto); aiNewState(actor, &houndGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void innocThinkSearch(DBloodActor *); static void innocThinkSearch(DBloodActor*);
static void innocThinkGoto(DBloodActor *); static void innocThinkGoto(DBloodActor*);
static void innocThinkChase(DBloodActor *); static void innocThinkChase(DBloodActor*);
AISTATE innocentIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE innocentIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
AISTATE innocentSearch = { kAiStateSearch, 6, -1, 1800, NULL, aiMoveForward, innocThinkSearch, &innocentIdle }; AISTATE innocentSearch = { kAiStateSearch, 6, -1, 1800, NULL, aiMoveForward, innocThinkSearch, &innocentIdle };
@ -43,75 +43,75 @@ AISTATE innocentGoto = { kAiStateMove, 6, -1, 600, NULL, aiMoveForward, innocThi
static void innocThinkSearch(DBloodActor* actor) static void innocThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void innocThinkGoto(DBloodActor* actor) static void innocThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &innocentSearch); aiNewState(actor, &innocentSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void innocThinkChase(DBloodActor* actor) static void innocThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &innocentGoto); aiNewState(actor, &innocentGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &innocentSearch); aiNewState(actor, &innocentSearch);
return; return;
} }
if (IsPlayerSprite(pTarget)) if (IsPlayerSprite(pTarget))
{ {
aiNewState(actor, &innocentSearch); aiNewState(actor, &innocentSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x666 && abs(nDeltaAngle) < 85) if (nDist < 0x666 && abs(nDeltaAngle) < 85)
aiNewState(actor, &innocentIdle); aiNewState(actor, &innocentIdle);
return; return;
} }
} }
} }
aiPlay3DSound(actor, 7000+Random(6), AI_SFX_PRIORITY_1, -1); aiPlay3DSound(actor, 7000 + Random(6), AI_SFX_PRIORITY_1, -1);
aiNewState(actor, &innocentGoto); aiNewState(actor, &innocentGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }

View file

@ -53,202 +53,202 @@ AISTATE tentacleChase = { kAiStateChase, 6, -1, 0, NULL, aiMoveTurn, aiPodChase,
void sub_6FF08(int, DBloodActor* actor) void sub_6FF08(int, DBloodActor* actor)
{ {
sfxPlay3DSound(actor, 2503, -1, 0); sfxPlay3DSound(actor, 2503, -1, 0);
} }
void sub_6FF54(int, DBloodActor* actor) void sub_6FF54(int, DBloodActor* actor)
{ {
sfxPlay3DSound(actor, 2500, -1, 0); sfxPlay3DSound(actor, 2500, -1, 0);
} }
void podAttack(int, DBloodActor* actor) void podAttack(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int x = pTarget->x-pSprite->x; int x = pTarget->x - pSprite->x;
int y = pTarget->y-pSprite->y; int y = pTarget->y - pSprite->y;
int dz = pTarget->z-pSprite->z; int dz = pTarget->z - pSprite->z;
x += Random2(1000); x += Random2(1000);
y += Random2(1000); y += Random2(1000);
int nDist = approxDist(x, y); int nDist = approxDist(x, y);
int nDist2 = nDist / 540; int nDist2 = nDist / 540;
DBloodActor* pMissile = nullptr; DBloodActor* pMissile = nullptr;
switch (pSprite->type) switch (pSprite->type)
{ {
case kDudePodGreen: case kDudePodGreen:
dz += 8000; dz += 8000;
if (pDudeInfo->seeDist*0.1 < nDist) if (pDudeInfo->seeDist * 0.1 < nDist)
{ {
if (Chance(0x8000)) if (Chance(0x8000))
sfxPlay3DSound(actor, 2474, -1, 0); sfxPlay3DSound(actor, 2474, -1, 0);
else else
sfxPlay3DSound(actor, 2475, -1, 0); sfxPlay3DSound(actor, 2475, -1, 0);
pMissile = actFireThing(actor, 0, -8000, dz/128-14500, kThingPodGreenBall, (nDist2<<23)/120); pMissile = actFireThing(actor, 0, -8000, dz / 128 - 14500, kThingPodGreenBall, (nDist2 << 23) / 120);
} }
if (pMissile) if (pMissile)
seqSpawn(68, pMissile, -1); seqSpawn(68, pMissile, -1);
break; break;
case kDudePodFire: case kDudePodFire:
dz += 8000; dz += 8000;
if (pDudeInfo->seeDist*0.1 < nDist) if (pDudeInfo->seeDist * 0.1 < nDist)
{ {
sfxPlay3DSound(actor, 2454, -1, 0); sfxPlay3DSound(actor, 2454, -1, 0);
pMissile = actFireThing(actor, 0, -8000, dz/128-14500, kThingPodFireBall, (nDist2<<23)/120); pMissile = actFireThing(actor, 0, -8000, dz / 128 - 14500, kThingPodFireBall, (nDist2 << 23) / 120);
} }
if (pMissile) if (pMissile)
seqSpawn(22, pMissile, -1); seqSpawn(22, pMissile, -1);
break; break;
} }
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
sub_746D4(pSprite, 240); sub_746D4(pSprite, 240);
} }
void sub_70284(int, DBloodActor* actor) void sub_70284(int, DBloodActor* actor)
{ {
auto pSprite = &actor->s(); auto pSprite = &actor->s();
sfxPlay3DSound(actor, 2502, -1, 0); sfxPlay3DSound(actor, 2502, -1, 0);
int nDist, nBurn; int nDist, nBurn;
DAMAGE_TYPE dmgType; DAMAGE_TYPE dmgType;
switch (pSprite->type) { switch (pSprite->type) {
case kDudeTentacleGreen: case kDudeTentacleGreen:
default: // ??? default: // ???
nBurn = 0; nBurn = 0;
dmgType = kDamageBullet; dmgType = kDamageBullet;
nDist = 50; nDist = 50;
break; break;
case kDudeTentacleFire: // ??? case kDudeTentacleFire: // ???
nBurn = (gGameOptions.nDifficulty*120)>>2; nBurn = (gGameOptions.nDifficulty * 120) >> 2;
dmgType = kDamageExplode; dmgType = kDamageExplode;
nDist = 75; nDist = 75;
break; break;
} }
actRadiusDamage(actor, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, nDist, 1, 5*(1+gGameOptions.nDifficulty), dmgType, 2, nBurn); actRadiusDamage(actor, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, nDist, 1, 5 * (1 + gGameOptions.nDifficulty), dmgType, 2, nBurn);
} }
static void aiPodSearch(DBloodActor* actor) static void aiPodSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void aiPodMove(DBloodActor* actor) static void aiPodMove(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) { if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) {
switch (pSprite->type) { switch (pSprite->type) {
case kDudePodGreen: case kDudePodGreen:
case kDudePodFire: case kDudePodFire:
aiNewState(actor, &podSearch); aiNewState(actor, &podSearch);
break; break;
case kDudeTentacleGreen: case kDudeTentacleGreen:
case kDudeTentacleFire: case kDudeTentacleFire:
aiNewState(actor, &tentacleSearch); aiNewState(actor, &tentacleSearch);
break; break;
} }
} }
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void aiPodChase(DBloodActor* actor) static void aiPodChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) { if (actor->GetTarget() == nullptr) {
switch (pSprite->type) { switch (pSprite->type) {
case kDudePodGreen: case kDudePodGreen:
case kDudePodFire: case kDudePodFire:
aiNewState(actor, &podMove); aiNewState(actor, &podMove);
break; break;
case kDudeTentacleGreen: case kDudeTentacleGreen:
case kDudeTentacleFire: case kDudeTentacleFire:
aiNewState(actor, &tentacleMove); aiNewState(actor, &tentacleMove);
break; break;
} }
return; return;
} }
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) { if (pXTarget->health == 0) {
switch (pSprite->type) { switch (pSprite->type) {
case kDudePodGreen: case kDudePodGreen:
case kDudePodFire: case kDudePodFire:
aiNewState(actor, &podSearch); aiNewState(actor, &podSearch);
break; break;
case kDudeTentacleGreen: case kDudeTentacleGreen:
case kDudeTentacleFire: case kDudeTentacleFire:
aiNewState(actor, &tentacleSearch); aiNewState(actor, &tentacleSearch);
break; break;
} }
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (abs(nDeltaAngle) < 85 && pTarget->type != kDudePodGreen && pTarget->type != kDudePodFire) { if (abs(nDeltaAngle) < 85 && pTarget->type != kDudePodGreen && pTarget->type != kDudePodFire) {
switch (pSprite->type) { switch (pSprite->type) {
case kDudePodGreen: case kDudePodGreen:
case kDudePodFire: case kDudePodFire:
aiNewState(actor, &podStartChase); aiNewState(actor, &podStartChase);
break; break;
case kDudeTentacleGreen: case kDudeTentacleGreen:
case kDudeTentacleFire: case kDudeTentacleFire:
aiNewState(actor, &tentacleStartChase); aiNewState(actor, &tentacleStartChase);
break; break;
} }
} }
return; return;
} }
} }
} }
switch (pSprite->type) { switch (pSprite->type) {
case kDudePodGreen: case kDudePodGreen:
case kDudePodFire: case kDudePodFire:
aiNewState(actor, &podMove); aiNewState(actor, &podMove);
break; break;
case kDudeTentacleGreen: case kDudeTentacleGreen:
case kDudeTentacleFire: case kDudeTentacleFire:
aiNewState(actor, &tentacleMove); aiNewState(actor, &tentacleMove);
break; break;
} }
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void ratThinkSearch(DBloodActor *); static void ratThinkSearch(DBloodActor*);
static void ratThinkGoto(DBloodActor *); static void ratThinkGoto(DBloodActor*);
static void ratThinkChase(DBloodActor *); static void ratThinkChase(DBloodActor*);
AISTATE ratIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE ratIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
AISTATE ratSearch = { kAiStateSearch, 7, -1, 1800, NULL, aiMoveForward, ratThinkSearch, &ratIdle }; AISTATE ratSearch = { kAiStateSearch, 7, -1, 1800, NULL, aiMoveForward, ratThinkSearch, &ratIdle };
@ -44,86 +44,86 @@ AISTATE ratBite = { kAiStateChase, 6, nRatBiteClient, 120, NULL, NULL, NULL, &ra
void ratBiteSeqCallback(int, DBloodActor* actor) void ratBiteSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
if (IsPlayerSprite(pTarget)) if (IsPlayerSprite(pTarget))
actFireVector(actor, 0, 0, dx, dy, pTarget->z-pSprite->z, kVectorRatBite); actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorRatBite);
} }
static void ratThinkSearch(DBloodActor* actor) static void ratThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void ratThinkGoto(DBloodActor* actor) static void ratThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &ratSearch); aiNewState(actor, &ratSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void ratThinkChase(DBloodActor* actor) static void ratThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &ratGoto); aiNewState(actor, &ratGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &ratSearch); aiNewState(actor, &ratSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &ratSearch); aiNewState(actor, &ratSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x399 && abs(nDeltaAngle) < 85) if (nDist < 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &ratBite); aiNewState(actor, &ratBite);
return; return;
} }
} }
} }
aiNewState(actor, &ratGoto); aiNewState(actor, &ratGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void spidThinkSearch(DBloodActor *); static void spidThinkSearch(DBloodActor*);
static void spidThinkGoto(DBloodActor *); static void spidThinkGoto(DBloodActor*);
static void spidThinkChase(DBloodActor *); static void spidThinkChase(DBloodActor*);
AISTATE spidIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE spidIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
@ -46,218 +46,219 @@ AISTATE spidBirth = { kAiStateOther, 0, nSpidBirthClient, 60, NULL, NULL, NULL,
static char spidBlindEffect(DBloodActor* dudeactor, int nBlind, int max) static char spidBlindEffect(DBloodActor* dudeactor, int nBlind, int max)
{ {
spritetype *pDude = &dudeactor->s(); spritetype* pDude = &dudeactor->s();
if (IsPlayerSprite(pDude)) if (IsPlayerSprite(pDude))
{ {
nBlind <<= 4; nBlind <<= 4;
max <<= 4; max <<= 4;
PLAYER *pPlayer = &gPlayer[pDude->type-kDudePlayer1]; PLAYER* pPlayer = &gPlayer[pDude->type - kDudePlayer1];
if (pPlayer->blindEffect < max) if (pPlayer->blindEffect < max)
{ {
pPlayer->blindEffect = ClipHigh(pPlayer->blindEffect+nBlind, max); pPlayer->blindEffect = ClipHigh(pPlayer->blindEffect + nBlind, max);
return 1; return 1;
} }
} }
return 0; return 0;
} }
void SpidBiteSeqCallback(int, DBloodActor* actor) void SpidBiteSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
dx += Random2(2000); dx += Random2(2000);
dy += Random2(2000); dy += Random2(2000);
int dz = Random2(2000); int dz = Random2(2000);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
auto const target = actor->GetTarget();
spritetype *pTarget = &target->s();
XSPRITE* pXTarget = &target->x();
if (IsPlayerSprite(pTarget))
{
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
if (hit == 3 && gHitInfo.hitactor->IsPlayerActor())
{
dz += pTarget->z - pSprite->z;
PLAYER *pPlayer = &gPlayer[pTarget->type - kDudePlayer1];
switch (pSprite->type)
{
case kDudeSpiderBrown:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
if (IsPlayerSprite(pTarget) && !pPlayer->godMode && powerupCheck(pPlayer, kPwUpDeathMask) <= 0 && Chance(0x4000))
powerupActivate(pPlayer, kPwUpDeliriumShroom);
break;
case kDudeSpiderRed:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
if (Chance(0x5000)) spidBlindEffect(target, 4, 16);
break;
case kDudeSpiderBlack:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
spidBlindEffect(target, 8, 16);
break;
case kDudeSpiderMother:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
dx += Random2(2000); auto const target = actor->GetTarget();
dy += Random2(2000); spritetype* pTarget = &target->s();
dz += Random2(2000); XSPRITE* pXTarget = &target->x();
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite); if (IsPlayerSprite(pTarget))
spidBlindEffect(target, 8, 16); {
break; int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
} if (hit == 3 && gHitInfo.hitactor->IsPlayerActor())
} {
dz += pTarget->z - pSprite->z;
PLAYER* pPlayer = &gPlayer[pTarget->type - kDudePlayer1];
switch (pSprite->type)
{
case kDudeSpiderBrown:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
if (IsPlayerSprite(pTarget) && !pPlayer->godMode && powerupCheck(pPlayer, kPwUpDeathMask) <= 0 && Chance(0x4000))
powerupActivate(pPlayer, kPwUpDeliriumShroom);
break;
case kDudeSpiderRed:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
if (Chance(0x5000)) spidBlindEffect(target, 4, 16);
break;
case kDudeSpiderBlack:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
spidBlindEffect(target, 8, 16);
break;
case kDudeSpiderMother:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
} dx += Random2(2000);
dy += Random2(2000);
dz += Random2(2000);
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
spidBlindEffect(target, 8, 16);
break;
}
}
}
} }
void SpidJumpSeqCallback(int, DBloodActor* actor) void SpidJumpSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
dx += Random2(200); dx += Random2(200);
dy += Random2(200); dy += Random2(200);
int dz = Random2(200); int dz = Random2(200);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
if (IsPlayerSprite(pTarget)) { if (IsPlayerSprite(pTarget)) {
dz += pTarget->z-pSprite->z; dz += pTarget->z - pSprite->z;
switch (pSprite->type) { switch (pSprite->type) {
case kDudeSpiderBrown: case kDudeSpiderBrown:
case kDudeSpiderRed: case kDudeSpiderRed:
case kDudeSpiderBlack: case kDudeSpiderBlack:
actor->xvel() = IntToFixed(dx); actor->xvel() = IntToFixed(dx);
actor->yvel() = IntToFixed(dy); actor->yvel() = IntToFixed(dy);
actor->zvel() = IntToFixed(dz); actor->zvel() = IntToFixed(dz);
break; break;
} }
} }
} }
void SpidBirthSeqCallback(int, DBloodActor* actor) void SpidBirthSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
DBloodActor* spawned = nullptr;
if (IsPlayerSprite(pTarget) && pDudeExtraE->birthCounter < 10)
{
if (nDist < 0x1a00 && nDist > 0x1400 && abs(pSprite->ang-nAngle) < pDudeInfo->periphery)
spawned = actSpawnDude(actor, kDudeSpiderRed, pSprite->clipdist, 0);
else if (nDist < 0x1400 && nDist > 0xc00 && abs(pSprite->ang-nAngle) < pDudeInfo->periphery)
spawned = actSpawnDude(actor, kDudeSpiderBrown, pSprite->clipdist, 0);
else if (nDist < 0xc00 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
spawned = actSpawnDude(actor, kDudeSpiderBrown, pSprite->clipdist, 0);
if (spawned) DBloodActor* spawned = nullptr;
{ if (IsPlayerSprite(pTarget) && pDudeExtraE->birthCounter < 10)
pDudeExtraE->birthCounter++; {
spawned->SetOwner(spawned); if (nDist < 0x1a00 && nDist > 0x1400 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
gKillMgr.AddNewKill(1); spawned = actSpawnDude(actor, kDudeSpiderRed, pSprite->clipdist, 0);
} else if (nDist < 0x1400 && nDist > 0xc00 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
} spawned = actSpawnDude(actor, kDudeSpiderBrown, pSprite->clipdist, 0);
else if (nDist < 0xc00 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
spawned = actSpawnDude(actor, kDudeSpiderBrown, pSprite->clipdist, 0);
if (spawned)
{
pDudeExtraE->birthCounter++;
spawned->SetOwner(spawned);
gKillMgr.AddNewKill(1);
}
}
} }
static void spidThinkSearch(DBloodActor* actor) static void spidThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void spidThinkGoto(DBloodActor* actor) static void spidThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &spidSearch); aiNewState(actor, &spidSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void spidThinkChase(DBloodActor* actor) static void spidThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &spidGoto); aiNewState(actor, &spidGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &spidSearch); aiNewState(actor, &spidSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &spidSearch); aiNewState(actor, &spidSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) { if (nDist <= pDudeInfo->seeDist) {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) {
aiSetTarget(actor, actor->GetTarget());
switch (pSprite->type) {
case kDudeSpiderRed:
if (nDist < 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidBite);
break;
case kDudeSpiderBrown:
case kDudeSpiderBlack:
if (nDist < 0x733 && nDist > 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidJump);
else if (nDist < 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidBite);
break;
case kDudeSpiderMother:
if (nDist < 0x733 && nDist > 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidJump);
else if (Chance(0x8000))
aiNewState(actor, &spidBirth);
break;
}
return; if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) {
} if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) {
} aiSetTarget(actor, actor->GetTarget());
}
aiNewState(actor, &spidGoto); switch (pSprite->type) {
actor->SetTarget(nullptr); case kDudeSpiderRed:
if (nDist < 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidBite);
break;
case kDudeSpiderBrown:
case kDudeSpiderBlack:
if (nDist < 0x733 && nDist > 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidJump);
else if (nDist < 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidBite);
break;
case kDudeSpiderMother:
if (nDist < 0x733 && nDist > 0x399 && abs(nDeltaAngle) < 85)
aiNewState(actor, &spidJump);
else if (Chance(0x8000))
aiNewState(actor, &spidBirth);
break;
}
return;
}
}
}
aiNewState(actor, &spidGoto);
actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,10 +30,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void sub_72580(DBloodActor *); static void sub_72580(DBloodActor*);
static void sub_725A4(DBloodActor *); static void sub_725A4(DBloodActor*);
static void sub_72850(DBloodActor *); static void sub_72850(DBloodActor*);
static void sub_72934(DBloodActor *); static void sub_72934(DBloodActor*);
AISTATE tchernobogIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, sub_725A4, NULL }; AISTATE tchernobogIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, sub_725A4, NULL };
@ -48,306 +48,306 @@ AISTATE tcherno13AA28 = { kAiStateChase, 8, -1, 60, NULL, aiMoveTurn, NULL, &tch
void sub_71A90(int, DBloodActor* actor) void sub_71A90(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int nTarget = pTarget->index; int nTarget = pTarget->index;
int nOwner = pSprite->owner; int nOwner = pSprite->owner;
if (pXTarget->burnTime == 0) if (pXTarget->burnTime == 0)
evPost(nTarget, 3, 0, kCallbackFXFlameLick); evPost(nTarget, 3, 0, kCallbackFXFlameLick);
actBurnSprite(nOwner, pXTarget, 40); actBurnSprite(nOwner, pXTarget, 40);
if (Chance(0x6000)) if (Chance(0x6000))
aiNewState(actor, &tcherno13A9D4); aiNewState(actor, &tcherno13A9D4);
} }
void sub_71BD4(int, DBloodActor* actor) void sub_71BD4(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int height = pSprite->yrepeat*pDudeInfo->eyeHeight; int height = pSprite->yrepeat * pDudeInfo->eyeHeight;
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = height; int z = height;
TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 }; TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 };
Aim aim; Aim aim;
aim.dx = CosScale16(pSprite->ang); aim.dx = CosScale16(pSprite->ang);
aim.dy = SinScale16(pSprite->ang); aim.dy = SinScale16(pSprite->ang);
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
BloodStatIterator it(kStatDude); BloodStatIterator it(kStatDude);
while (auto actor2 = it.Next()) while (auto actor2 = it.Next())
{ {
spritetype* pSprite2 = &actor2->s(); spritetype* pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags & 8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
int y2 = pSprite2->y; int y2 = pSprite2->y;
int z2 = pSprite2->z; int z2 = pSprite2->z;
int nDist = approxDist(x2-x, y2-y); int nDist = approxDist(x2 - x, y2 - y);
if (nDist == 0 || nDist > 0x2800) if (nDist == 0 || nDist > 0x2800)
continue; continue;
if (tt.at10) if (tt.at10)
{ {
int t = DivScale(nDist, tt.at10, 12); int t = DivScale(nDist, tt.at10, 12);
x2 += (actor->xvel() * t) >> 12; x2 += (actor->xvel() * t) >> 12;
y2 += (actor->yvel() * t) >> 12; y2 += (actor->yvel() * t) >> 12;
z2 += (actor->zvel() * t) >> 8; z2 += (actor->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
int tz = z+MulScale(actor->dudeSlope, nDist, 10); int tz = z + MulScale(actor->dudeSlope, nDist, 10);
int tsr = MulScale(9460, nDist, 10); int tsr = MulScale(9460, nDist, 10);
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite2, &top, &bottom); GetSpriteExtents(pSprite2, &top, &bottom);
if (tz-tsr > bottom || tz+tsr < top) if (tz - tsr > bottom || tz + tsr < top)
continue; continue;
int dx = (tx-x2)>>4; int dx = (tx - x2) >> 4;
int dy = (ty-y2)>>4; int dy = (ty - y2) >> 4;
int dz = (tz-z2)>>8; int dz = (tz - z2) >> 8;
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz); int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
if (nDist2 < nClosest) if (nDist2 < nClosest)
{ {
int nAngle = getangle(x2-x, y2-y); int nAngle = getangle(x2 - x, y2 - y);
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024; int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
if (abs(nDeltaAngle) <= tt.at8) if (abs(nDeltaAngle) <= tt.at8)
{ {
int tz = pSprite2->z-pSprite->z; int tz = pSprite2->z - pSprite->z;
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum)) if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
{ {
nClosest = nDist2; nClosest = nDist2;
aim.dx = CosScale16(nAngle); aim.dx = CosScale16(nAngle);
aim.dy = SinScale16(nAngle); aim.dy = SinScale16(nAngle);
aim.dz = DivScale(tz, nDist, 10); aim.dz = DivScale(tz, nDist, 10);
} }
else else
aim.dz = tz; aim.dz = tz;
} }
} }
} }
actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog); actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog);
actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog); actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog);
} }
void sub_720AC(int, DBloodActor* actor) void sub_720AC(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int height = pSprite->yrepeat*pDudeInfo->eyeHeight; int height = pSprite->yrepeat * pDudeInfo->eyeHeight;
int ax, ay, az; int ax, ay, az;
ax = CosScale16(pSprite->ang); ax = CosScale16(pSprite->ang);
ay = SinScale16(pSprite->ang); ay = SinScale16(pSprite->ang);
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = height; int z = height;
TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 }; TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 };
Aim aim; Aim aim;
aim.dx = ax; aim.dx = ax;
aim.dy = ay; aim.dy = ay;
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
az = 0; az = 0;
BloodStatIterator it(kStatDude); BloodStatIterator it(kStatDude);
while (auto actor2 = it.Next()) while (auto actor2 = it.Next())
{ {
spritetype* pSprite2 = &actor2->s(); spritetype* pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags & 8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
int y2 = pSprite2->y; int y2 = pSprite2->y;
int z2 = pSprite2->z; int z2 = pSprite2->z;
int nDist = approxDist(x2-x, y2-y); int nDist = approxDist(x2 - x, y2 - y);
if (nDist == 0 || nDist > 0x2800) if (nDist == 0 || nDist > 0x2800)
continue; continue;
if (tt.at10) if (tt.at10)
{ {
int t = DivScale(nDist, tt.at10, 12); int t = DivScale(nDist, tt.at10, 12);
x2 += (actor->xvel()*t)>>12; x2 += (actor->xvel() * t) >> 12;
y2 += (actor->yvel()*t)>>12; y2 += (actor->yvel() * t) >> 12;
z2 += (actor->zvel()*t)>>8; z2 += (actor->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
int tz = z+MulScale(actor->dudeSlope, nDist, 10); int tz = z + MulScale(actor->dudeSlope, nDist, 10);
int tsr = MulScale(9460, nDist, 10); int tsr = MulScale(9460, nDist, 10);
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite2, &top, &bottom); GetSpriteExtents(pSprite2, &top, &bottom);
if (tz-tsr > bottom || tz+tsr < top) if (tz - tsr > bottom || tz + tsr < top)
continue; continue;
int dx = (tx-x2)>>4; int dx = (tx - x2) >> 4;
int dy = (ty-y2)>>4; int dy = (ty - y2) >> 4;
int dz = (tz-z2)>>8; int dz = (tz - z2) >> 8;
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz); int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
if (nDist2 < nClosest) if (nDist2 < nClosest)
{ {
int nAngle = getangle(x2-x, y2-y); int nAngle = getangle(x2 - x, y2 - y);
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024; int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
if (abs(nDeltaAngle) <= tt.at8) if (abs(nDeltaAngle) <= tt.at8)
{ {
int tz = pSprite2->z-pSprite->z; int tz = pSprite2->z - pSprite->z;
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum)) if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
{ {
nClosest = nDist2; nClosest = nDist2;
aim.dx = CosScale16(nAngle); aim.dx = CosScale16(nAngle);
aim.dy = SinScale16(nAngle); aim.dy = SinScale16(nAngle);
aim.dz = DivScale(tz, nDist, 10); aim.dz = DivScale(tz, nDist, 10);
} }
else else
aim.dz = tz; aim.dz = tz;
} }
} }
} }
actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, -aim.dz, kMissileFireballTchernobog); actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, -aim.dz, kMissileFireballTchernobog);
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFireballTchernobog); actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFireballTchernobog);
} }
static void sub_72580(DBloodActor* actor) static void sub_72580(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void sub_725A4(DBloodActor* actor) static void sub_725A4(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10) if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++; pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D* pTarget = &actor->basePoint(); POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &tcherno13AA28); aiNewState(actor, &tcherno13AA28);
return; return;
} }
if (Chance(pDudeInfo->alertChance)) if (Chance(pDudeInfo->alertChance))
{ {
for (int p = connecthead; p >= 0; p = connectpoint2[p]) for (int p = connecthead; p >= 0; p = connectpoint2[p])
{ {
PLAYER *pPlayer = &gPlayer[p]; PLAYER* pPlayer = &gPlayer[p];
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0) if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
continue; continue;
int x = pPlayer->pSprite->x; int x = pPlayer->pSprite->x;
int y = pPlayer->pSprite->y; int y = pPlayer->pSprite->y;
int z = pPlayer->pSprite->z; int z = pPlayer->pSprite->z;
int nSector = pPlayer->pSprite->sectnum; int nSector = pPlayer->pSprite->sectnum;
int dx = x-pSprite->x; int dx = x - pSprite->x;
int dy = y-pSprite->y; int dy = y - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist) if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
continue; continue;
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum)) if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
continue; continue;
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
aiSetTarget(actor, pPlayer->actor()); aiSetTarget(actor, pPlayer->actor());
aiActivateDude(actor); aiActivateDude(actor);
} }
else if (nDist < pDudeInfo->hearDist) else if (nDist < pDudeInfo->hearDist)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
aiSetTarget(actor, x, y, z); aiSetTarget(actor, x, y, z);
aiActivateDude(actor); aiActivateDude(actor);
} }
else else
continue; continue;
break; break;
} }
} }
} }
static void sub_72850(DBloodActor* actor) static void sub_72850(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &tchernobogSearch); aiNewState(actor, &tchernobogSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void sub_72934(DBloodActor* actor) static void sub_72934(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &tcherno13A9B8); aiNewState(actor, &tcherno13A9B8);
return; return;
} }
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); ///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return; return;
} }
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &tchernobogSearch); aiNewState(actor, &tchernobogSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
{ {
aiNewState(actor, &tchernobogSearch); aiNewState(actor, &tchernobogSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x1f00 && nDist > 0xd00 && abs(nDeltaAngle) < 85) if (nDist < 0x1f00 && nDist > 0xd00 && abs(nDeltaAngle) < 85)
aiNewState(actor, &tcherno13AA0C); aiNewState(actor, &tcherno13AA0C);
else if (nDist < 0xd00 && nDist > 0xb00 && abs(nDeltaAngle) < 85) else if (nDist < 0xd00 && nDist > 0xb00 && abs(nDeltaAngle) < 85)
aiNewState(actor, &tcherno13A9D4); aiNewState(actor, &tcherno13A9D4);
else if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85) else if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85)
aiNewState(actor, &tcherno13A9F0); aiNewState(actor, &tcherno13A9F0);
return; return;
} }
} }
} }
aiNewState(actor, &tcherno13A9B8); aiNewState(actor, &tcherno13A9B8);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,15 +30,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void zombaThinkSearch(DBloodActor *); static void zombaThinkSearch(DBloodActor*);
static void zombaThinkGoto(DBloodActor *); static void zombaThinkGoto(DBloodActor*);
static void zombaThinkChase(DBloodActor *); static void zombaThinkChase(DBloodActor*);
static void zombaThinkPonder(DBloodActor *); static void zombaThinkPonder(DBloodActor*);
static void myThinkTarget(DBloodActor *); static void myThinkTarget(DBloodActor*);
static void myThinkSearch(DBloodActor *); static void myThinkSearch(DBloodActor*);
static void entryEZombie(DBloodActor *); static void entryEZombie(DBloodActor*);
static void entryAIdle(DBloodActor *); static void entryAIdle(DBloodActor*);
static void entryEStand(DBloodActor *); static void entryEStand(DBloodActor*);
AISTATE zombieAIdle = { kAiStateIdle, 0, -1, 0, entryAIdle, NULL, aiThinkTarget, NULL }; AISTATE zombieAIdle = { kAiStateIdle, 0, -1, 0, entryAIdle, NULL, aiThinkTarget, NULL };
@ -61,224 +61,224 @@ AISTATE zombie13AC2C = { kAiStateOther, 11, nStandClient, 0, entryEZombie, NULL,
void HackSeqCallback(int, DBloodActor* actor) void HackSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type); DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
int tx = pXSprite->targetX-pSprite->x; int tx = pXSprite->targetX - pSprite->x;
int ty = pXSprite->targetY-pSprite->y; int ty = pXSprite->targetY - pSprite->y;
int nAngle = getangle(tx, ty); int nAngle = getangle(tx, ty);
int height = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2; int height = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2;
int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2; int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2;
int dz = height-height2; int dz = height - height2;
int dx = CosScale16(nAngle); int dx = CosScale16(nAngle);
int dy = SinScale16(nAngle); int dy = SinScale16(nAngle);
sfxPlay3DSound(pSprite, 1101, 1, 0); sfxPlay3DSound(pSprite, 1101, 1, 0);
actFireVector(actor, 0, 0, dx, dy, dz, kVectorAxe); actFireVector(actor, 0, 0, dx, dy, dz, kVectorAxe);
} }
void StandSeqCallback(int, DBloodActor* actor) void StandSeqCallback(int, DBloodActor* actor)
{ {
sfxPlay3DSound(actor, 1102, -1, 0); sfxPlay3DSound(actor, 1102, -1, 0);
} }
static void zombaThinkSearch(DBloodActor* actor) static void zombaThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiLookForTarget(actor); aiLookForTarget(actor);
} }
static void zombaThinkGoto(DBloodActor* actor) static void zombaThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 921 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 921 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &zombieASearch); aiNewState(actor, &zombieASearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void zombaThinkChase(DBloodActor* actor) static void zombaThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &zombieASearch); aiNewState(actor, &zombieASearch);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &zombieASearch); aiNewState(actor, &zombieASearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpDeathMaskUseless) > 0)) if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpDeathMaskUseless) > 0))
{ {
aiNewState(actor, &zombieAGoto); aiNewState(actor, &zombieAGoto);
return; return;
} }
// If the zombie gets whacked while rising from the grave it never executes this change and if it isn't done here at the very latest, will just aimlessly run around. // If the zombie gets whacked while rising from the grave it never executes this change and if it isn't done here at the very latest, will just aimlessly run around.
if (!VanillaMode() && pSprite->type == kDudeZombieAxeBuried) if (!VanillaMode() && pSprite->type == kDudeZombieAxeBuried)
pSprite->type = kDudeZombieAxeNormal; pSprite->type = kDudeZombieAxeNormal;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (abs(nDeltaAngle) <= pDudeInfo->periphery) if (abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x400 && abs(nDeltaAngle) < 85) if (nDist < 0x400 && abs(nDeltaAngle) < 85)
aiNewState(actor, &zombieAHack); aiNewState(actor, &zombieAHack);
return; return;
} }
} }
} }
aiNewState(actor, &zombieAGoto); aiNewState(actor, &zombieAGoto);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void zombaThinkPonder(DBloodActor* actor) static void zombaThinkPonder(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &zombieASearch); aiNewState(actor, &zombieASearch);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &zombieASearch); aiNewState(actor, &zombieASearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpDeathMaskUseless) > 0)) if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpDeathMaskUseless) > 0))
{ {
aiNewState(actor, &zombieAGoto); aiNewState(actor, &zombieAGoto);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (abs(nDeltaAngle) <= pDudeInfo->periphery) if (abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x400) if (nDist < 0x400)
{ {
if (abs(nDeltaAngle) < 85) if (abs(nDeltaAngle) < 85)
{ {
sfxPlay3DSound(pSprite, 1101, 1, 0); sfxPlay3DSound(pSprite, 1101, 1, 0);
aiNewState(actor, &zombieAHack); aiNewState(actor, &zombieAHack);
} }
return; return;
} }
} }
} }
} }
aiNewState(actor, &zombieAChase); aiNewState(actor, &zombieAChase);
} }
static void myThinkTarget(DBloodActor* actor) static void myThinkTarget(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
for (int p = connecthead; p >= 0; p = connectpoint2[p]) for (int p = connecthead; p >= 0; p = connectpoint2[p])
{ {
PLAYER *pPlayer = &gPlayer[p]; PLAYER* pPlayer = &gPlayer[p];
int nOwner = (pSprite->owner & 0x1000) ? (pSprite->owner&0xfff) : -1; int nOwner = (pSprite->owner & 0x1000) ? (pSprite->owner & 0xfff) : -1;
if (nOwner == pPlayer->nSprite || pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0) if (nOwner == pPlayer->nSprite || pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
continue; continue;
int x = pPlayer->pSprite->x; int x = pPlayer->pSprite->x;
int y = pPlayer->pSprite->y; int y = pPlayer->pSprite->y;
int z = pPlayer->pSprite->z; int z = pPlayer->pSprite->z;
int nSector = pPlayer->pSprite->sectnum; int nSector = pPlayer->pSprite->sectnum;
int dx = x-pSprite->x; int dx = x - pSprite->x;
int dy = y-pSprite->y; int dy = y - pSprite->y;
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist) if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
continue; continue;
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum)) if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
continue; continue;
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, pPlayer->actor()); aiSetTarget(actor, pPlayer->actor());
aiActivateDude(actor); aiActivateDude(actor);
} }
else if (nDist < pDudeInfo->hearDist) else if (nDist < pDudeInfo->hearDist)
{ {
aiSetTarget(actor, x, y, z); aiSetTarget(actor, x, y, z);
aiActivateDude(actor); aiActivateDude(actor);
} }
else else
continue; continue;
break; break;
} }
} }
static void myThinkSearch(DBloodActor* actor) static void myThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
myThinkTarget(actor); myThinkTarget(actor);
} }
static void entryEZombie(DBloodActor* actor) static void entryEZombie(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
pSprite->type = kDudeZombieAxeNormal; pSprite->type = kDudeZombieAxeNormal;
pSprite->flags |= 1; pSprite->flags |= 1;
} }
static void entryAIdle(DBloodActor* actor) static void entryAIdle(DBloodActor* actor)
{ {
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
static void entryEStand(DBloodActor* actor) static void entryEStand(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
sfxPlay3DSound(pSprite, 1100, -1, 0); sfxPlay3DSound(pSprite, 1100, -1, 0);
pSprite->ang = getangle(pXSprite->targetX-pSprite->x, pXSprite->targetY-pSprite->y); pSprite->ang = getangle(pXSprite->targetX - pSprite->x, pXSprite->targetY - pSprite->y);
} }
END_BLD_NS END_BLD_NS

View file

@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static void zombfThinkSearch(DBloodActor *actor); static void zombfThinkSearch(DBloodActor* actor);
static void zombfThinkGoto(DBloodActor *actor); static void zombfThinkGoto(DBloodActor* actor);
static void zombfThinkChase(DBloodActor *actor); static void zombfThinkChase(DBloodActor* actor);
AISTATE zombieFIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE zombieFIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
@ -48,169 +48,169 @@ AISTATE zombieFTeslaRecoil = { kAiStateRecoil, 4, -1, 0, NULL, NULL, NULL, &zomb
void zombfHackSeqCallback(int, DBloodActor* actor) void zombfHackSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (pSprite->type != kDudeZombieButcher) if (pSprite->type != kDudeZombieButcher)
return; return;
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat); int height = (pDudeInfo->eyeHeight * pSprite->yrepeat);
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type); DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
int height2 = (pDudeInfoT->eyeHeight*pTarget->yrepeat); int height2 = (pDudeInfoT->eyeHeight * pTarget->yrepeat);
actFireVector(actor, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), height-height2, kVectorCleaver); actFireVector(actor, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), height - height2, kVectorCleaver);
} }
void PukeSeqCallback(int, DBloodActor* actor) void PukeSeqCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type); DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat); int height = (pDudeInfo->eyeHeight * pSprite->yrepeat);
int height2 = (pDudeInfoT->eyeHeight*pTarget->yrepeat); int height2 = (pDudeInfoT->eyeHeight * pTarget->yrepeat);
int tx = pXSprite->targetX-pSprite->x; int tx = pXSprite->targetX - pSprite->x;
int ty = pXSprite->targetY-pSprite->y; int ty = pXSprite->targetY - pSprite->y;
int nAngle = getangle(tx, ty); int nAngle = getangle(tx, ty);
int dx = CosScale16(nAngle); int dx = CosScale16(nAngle);
int dy = SinScale16(nAngle); int dy = SinScale16(nAngle);
sfxPlay3DSound(pSprite, 1203, 1, 0); sfxPlay3DSound(pSprite, 1203, 1, 0);
actFireMissile(pSprite, 0, -(height-height2), dx, dy, 0, kMissilePukeGreen); actFireMissile(pSprite, 0, -(height - height2), dx, dy, 0, kMissilePukeGreen);
} }
void ThrowSeqCallback(int, DBloodActor* actor) void ThrowSeqCallback(int, DBloodActor* actor)
{ {
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
actFireMissile(pSprite, 0, -getDudeInfo(pSprite->type)->eyeHeight, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileButcherKnife); actFireMissile(pSprite, 0, -getDudeInfo(pSprite->type)->eyeHeight, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileButcherKnife);
} }
static void zombfThinkSearch(DBloodActor* actor) static void zombfThinkSearch(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
aiChooseDirection(actor,pXSprite->goalAng); aiChooseDirection(actor, pXSprite->goalAng);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void zombfThinkGoto(DBloodActor* actor) static void zombfThinkGoto(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int dx = pXSprite->targetX-pSprite->x; int dx = pXSprite->targetX - pSprite->x;
int dy = pXSprite->targetY-pSprite->y; int dy = pXSprite->targetY - pSprite->y;
int nAngle = getangle(dx, dy); int nAngle = getangle(dx, dy);
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
aiChooseDirection(actor,nAngle); aiChooseDirection(actor, nAngle);
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
aiNewState(actor, &zombieFSearch); aiNewState(actor, &zombieFSearch);
aiThinkTarget(actor); aiThinkTarget(actor);
} }
static void zombfThinkChase(DBloodActor* actor) static void zombfThinkChase(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
{ {
aiNewState(actor, &zombieFGoto); aiNewState(actor, &zombieFGoto);
return; return;
} }
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s(); spritetype* pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x(); XSPRITE* pXTarget = &actor->GetTarget()->x();
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
aiChooseDirection(actor,getangle(dx, dy)); aiChooseDirection(actor, getangle(dx, dy));
if (pXTarget->health == 0) if (pXTarget->health == 0)
{ {
aiNewState(actor, &zombieFSearch); aiNewState(actor, &zombieFSearch);
return; return;
} }
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpDeathMaskUseless) > 0)) if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpDeathMaskUseless) > 0))
{ {
aiNewState(actor, &zombieFSearch); aiNewState(actor, &zombieFSearch);
return; return;
} }
int nDist = approxDist(dx, dy); int nDist = approxDist(dx, dy);
if (nDist <= pDudeInfo->seeDist) if (nDist <= pDudeInfo->seeDist)
{ {
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024; int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2; int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum)) if (cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pSprite->x, pSprite->y, pSprite->z - height, pSprite->sectnum))
{ {
if (abs(nDeltaAngle) <= pDudeInfo->periphery) if (abs(nDeltaAngle) <= pDudeInfo->periphery)
{ {
aiSetTarget(actor, actor->GetTarget()); aiSetTarget(actor, actor->GetTarget());
if (nDist < 0x1400 && nDist > 0xe00 && abs(nDeltaAngle) < 85) if (nDist < 0x1400 && nDist > 0xe00 && abs(nDeltaAngle) < 85)
{ {
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
switch (hit) switch (hit)
{ {
case -1: case -1:
aiNewState(actor, &zombieFThrow); aiNewState(actor, &zombieFThrow);
break; break;
case 3: case 3:
if (pSprite->type != gHitInfo.hitactor->s().type) if (pSprite->type != gHitInfo.hitactor->s().type)
aiNewState(actor, &zombieFThrow); aiNewState(actor, &zombieFThrow);
else else
aiNewState(actor, &zombieFDodge); aiNewState(actor, &zombieFDodge);
break; break;
default: default:
aiNewState(actor, &zombieFThrow); aiNewState(actor, &zombieFThrow);
break; break;
} }
} }
else if (nDist < 0x1400 && nDist > 0x600 && abs(nDeltaAngle) < 85) else if (nDist < 0x1400 && nDist > 0x600 && abs(nDeltaAngle) < 85)
{ {
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
switch (hit) switch (hit)
{ {
case -1: case -1:
aiNewState(actor, &zombieFPuke); aiNewState(actor, &zombieFPuke);
break; break;
case 3: case 3:
if (pSprite->type != gHitInfo.hitactor->s().type) if (pSprite->type != gHitInfo.hitactor->s().type)
aiNewState(actor, &zombieFPuke); aiNewState(actor, &zombieFPuke);
else else
aiNewState(actor, &zombieFDodge); aiNewState(actor, &zombieFDodge);
break; break;
default: default:
aiNewState(actor, &zombieFPuke); aiNewState(actor, &zombieFPuke);
break; break;
} }
} }
else if (nDist < 0x400 && abs(nDeltaAngle) < 85) else if (nDist < 0x400 && abs(nDeltaAngle) < 85)
{ {
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
switch (hit) switch (hit)
{ {
case -1: case -1:
aiNewState(actor, &zombieFHack); aiNewState(actor, &zombieFHack);
break; break;
case 3: case 3:
if (pSprite->type != gHitInfo.hitactor->s().type) if (pSprite->type != gHitInfo.hitactor->s().type)
aiNewState(actor, &zombieFHack); aiNewState(actor, &zombieFHack);
else else
aiNewState(actor, &zombieFDodge); aiNewState(actor, &zombieFDodge);
break; break;
default: default:
aiNewState(actor, &zombieFHack); aiNewState(actor, &zombieFHack);
break; break;
} }
} }
return; return;
} }
} }
} }
aiNewState(actor, &zombieFSearch); aiNewState(actor, &zombieFSearch);
actor->SetTarget(nullptr); actor->SetTarget(nullptr);
} }
END_BLD_NS END_BLD_NS