mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-12 03:00:38 +00:00
- reformatted the actor and ai sources.
This commit is contained in:
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
|
@ -43,403 +43,403 @@ static void batMoveFly(DBloodActor*);
|
|||
static void batMoveToCeil(DBloodActor*);
|
||||
|
||||
|
||||
AISTATE batIdle = {kAiStateIdle, 0, -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 batPonder = {kAiStateOther, 6, -1, 0, NULL, NULL, batThinkPonder, NULL };
|
||||
AISTATE batGoto = {kAiStateMove, 6, -1, 600, NULL, batMoveForward, batThinkGoto, &batFlyIdle };
|
||||
AISTATE batBite = {kAiStateChase, 7, nBatBiteClient, 60, NULL, NULL, NULL, &batPonder };
|
||||
AISTATE batRecoil = {kAiStateRecoil, 5, -1, 0, NULL, NULL, NULL, &batChase };
|
||||
AISTATE batSearch = {kAiStateSearch, 6, -1, 120, NULL, batMoveForward, batThinkSearch, &batFlyIdle };
|
||||
AISTATE batSwoop = {kAiStateOther, 6, -1, 60, NULL, batMoveSwoop, batThinkChase, &batChase };
|
||||
AISTATE batIdle = { kAiStateIdle, 0, -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 batPonder = { kAiStateOther, 6, -1, 0, NULL, NULL, batThinkPonder, NULL };
|
||||
AISTATE batGoto = { kAiStateMove, 6, -1, 600, NULL, batMoveForward, batThinkGoto, &batFlyIdle };
|
||||
AISTATE batBite = { kAiStateChase, 7, nBatBiteClient, 60, NULL, NULL, NULL, &batPonder };
|
||||
AISTATE batRecoil = { kAiStateRecoil, 5, -1, 0, NULL, NULL, NULL, &batChase };
|
||||
AISTATE batSearch = { kAiStateSearch, 6, -1, 120, NULL, batMoveForward, batThinkSearch, &batFlyIdle };
|
||||
AISTATE batSwoop = { kAiStateOther, 6, -1, 60, NULL, batMoveSwoop, batThinkChase, &batChase };
|
||||
AISTATE batFly = { kAiStateMove, 6, -1, 0, NULL, batMoveFly, batThinkChase, &batChase };
|
||||
AISTATE batTurn = {kAiStateMove, 6, -1, 60, NULL, aiMoveTurn, NULL, &batChase };
|
||||
AISTATE batHide = {kAiStateOther, 6, -1, 0, NULL, batMoveToCeil, batMoveForward, NULL };
|
||||
AISTATE batDodgeUp = {kAiStateMove, 6, -1, 120, 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 batDodgeDown = {kAiStateMove, 6, -1, 120, 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 batTurn = { kAiStateMove, 6, -1, 60, NULL, aiMoveTurn, NULL, &batChase };
|
||||
AISTATE batHide = { kAiStateOther, 6, -1, 0, NULL, batMoveToCeil, batMoveForward, NULL };
|
||||
AISTATE batDodgeUp = { kAiStateMove, 6, -1, 120, 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 batDodgeDown = { kAiStateMove, 6, -1, 120, NULL, batMoveDodgeDown, 0, &batChase };
|
||||
AISTATE batDodgeDownRight = { kAiStateMove, 6, -1, 90, NULL, batMoveDodgeDown, 0, &batChase };
|
||||
AISTATE batDodgeDownLeft = { kAiStateMove, 6, -1, 90, NULL, batMoveDodgeDown, 0, &batChase };
|
||||
|
||||
void batBiteSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype *pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2;
|
||||
int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2;
|
||||
actFireVector(actor, 0, 0, dx, dy, height2-height, kVectorBatBite);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2;
|
||||
int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2;
|
||||
actFireVector(actor, 0, 0, dx, dy, height2 - height, kVectorBatBite);
|
||||
}
|
||||
|
||||
static void batThinkTarget(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D *pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
aiNewState(actor, &batTurn);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER *pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x-pSprite->x;
|
||||
int dy = y-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D* pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
aiNewState(actor, &batTurn);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER* pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x - pSprite->x;
|
||||
int dy = y - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void batThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
batThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
batThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void batThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &batSearch);
|
||||
batThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &batSearch);
|
||||
batThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void batThinkPonder(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2;
|
||||
int height2 = (getDudeInfo(pTarget->type)->eyeHeight*pTarget->yrepeat)<<2;
|
||||
int 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))
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (height2-height < 0x3000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2-height > 0x5000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeDown);
|
||||
else if (height2-height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2-height > 0x6000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeDown);
|
||||
else if (height2-height < 0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2-height < 0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2-height > 0x4000)
|
||||
aiNewState(actor, &batDodgeDown);
|
||||
else
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
aiNewState(actor, &batGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
|
||||
int height2 = (getDudeInfo(pTarget->type)->eyeHeight * pTarget->yrepeat) << 2;
|
||||
int 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))
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (height2 - height < 0x3000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2 - height > 0x5000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeDown);
|
||||
else if (height2 - height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2 - height > 0x6000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeDown);
|
||||
else if (height2 - height < 0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2 - height < 0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400)
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
else if (height2 - height > 0x4000)
|
||||
aiNewState(actor, &batDodgeDown);
|
||||
else
|
||||
aiNewState(actor, &batDodgeUp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
aiNewState(actor, &batGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void batMoveDodgeUp(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x52aaa;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x52aaa;
|
||||
}
|
||||
|
||||
static void batMoveDodgeDown(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
if (pXSprite->dodgeDir == 0)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
if (pXSprite->dodgeDir == 0)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x44444;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x44444;
|
||||
}
|
||||
|
||||
static void batThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &batGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2;
|
||||
// Should be dudeInfo[pTarget->type-kDudeBase]
|
||||
int height2 = (pDudeInfo->eyeHeight*pTarget->yrepeat)<<2;
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
int floorZ = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
|
||||
if (height2-height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batBite);
|
||||
else if ((height2-height > 0x5000 || floorZ-bottom > 0x5000) && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batSwoop);
|
||||
else if ((height2-height < 0x3000 || floorZ-bottom < 0x3000) && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batFly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aiNewState(actor, &batFly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &batGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &batSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
|
||||
// Should be dudeInfo[pTarget->type-kDudeBase]
|
||||
int height2 = (pDudeInfo->eyeHeight * pTarget->yrepeat) << 2;
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
int floorZ = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
|
||||
if (height2 - height < 0x2000 && nDist < 0x200 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batBite);
|
||||
else if ((height2 - height > 0x5000 || floorZ - bottom > 0x5000) && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batSwoop);
|
||||
else if ((height2 - height < 0x3000 || floorZ - bottom < 0x3000) && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &batFly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aiNewState(actor, &batFly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &batHide);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &batHide);
|
||||
}
|
||||
|
||||
static void batMoveForward(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = pDudeInfo->frontSpeed<<2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang+256)&2047;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if ((unsigned int)Random(64) < 32 && nDist <= 0x200)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = pDudeInfo->frontSpeed << 2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang + 256) & 2047;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if ((unsigned int)Random(64) < 32 && nDist <= 0x200)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
}
|
||||
|
||||
static void batMoveSwoop(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = pDudeInfo->frontSpeed<<2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pXSprite->goalAng = (pSprite->ang+512)&2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x600) && nDist <= 0x200)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x44444;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = pDudeInfo->frontSpeed << 2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pXSprite->goalAng = (pSprite->ang + 512) & 2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x600) && nDist <= 0x200)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x44444;
|
||||
}
|
||||
|
||||
static void batMoveFly(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = pDudeInfo->frontSpeed<<2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pSprite->ang = (pSprite->ang+512)&2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x200)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x2d555;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = pDudeInfo->frontSpeed << 2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pSprite->ang = (pSprite->ang + 512) & 2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x200)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x2d555;
|
||||
}
|
||||
|
||||
void batMoveToCeil(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = pSprite->z;
|
||||
int nSector = pSprite->sectnum;
|
||||
if (z - pXSprite->targetZ < 0x1000)
|
||||
{
|
||||
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats;
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
pSprite->flags = 0;
|
||||
aiNewState(actor, &batIdle);
|
||||
}
|
||||
else
|
||||
aiSetTarget(actor, x, y, sector[nSector].ceilingz);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = pSprite->z;
|
||||
int nSector = pSprite->sectnum;
|
||||
if (z - pXSprite->targetZ < 0x1000)
|
||||
{
|
||||
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
pSprite->flags = 0;
|
||||
aiNewState(actor, &batIdle);
|
||||
}
|
||||
else
|
||||
aiSetTarget(actor, x, y, sector[nSector].ceilingz);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,17 +29,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void eelThinkTarget(DBloodActor *);
|
||||
static void eelThinkSearch(DBloodActor *);
|
||||
static void eelThinkGoto(DBloodActor *);
|
||||
static void eelThinkPonder(DBloodActor *);
|
||||
static void eelMoveDodgeUp(DBloodActor *);
|
||||
static void eelMoveDodgeDown(DBloodActor *);
|
||||
static void eelThinkChase(DBloodActor *);
|
||||
static void eelMoveForward(DBloodActor *);
|
||||
static void eelMoveSwoop(DBloodActor *);
|
||||
static void eelMoveAscend(DBloodActor *actor);
|
||||
static void eelMoveToCeil(DBloodActor *);
|
||||
static void eelThinkTarget(DBloodActor*);
|
||||
static void eelThinkSearch(DBloodActor*);
|
||||
static void eelThinkGoto(DBloodActor*);
|
||||
static void eelThinkPonder(DBloodActor*);
|
||||
static void eelMoveDodgeUp(DBloodActor*);
|
||||
static void eelMoveDodgeDown(DBloodActor*);
|
||||
static void eelThinkChase(DBloodActor*);
|
||||
static void eelMoveForward(DBloodActor*);
|
||||
static void eelMoveSwoop(DBloodActor*);
|
||||
static void eelMoveAscend(DBloodActor* actor);
|
||||
static void eelMoveToCeil(DBloodActor*);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype *pSprite = &actor->s();
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
|
||||
/*
|
||||
* workaround for
|
||||
* pXSprite->target >= 0 && pXSprite->target < kMaxSprites in file NBlood/source/blood/src/aiboneel.cpp at line 86
|
||||
* The value of pXSprite->target is -1.
|
||||
* copied from lines 177:181
|
||||
* resolves this case, but may cause other issues?
|
||||
*/
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* workaround for
|
||||
* pXSprite->target >= 0 && pXSprite->target < kMaxSprites in file NBlood/source/blood/src/aiboneel.cpp at line 86
|
||||
* The value of pXSprite->target is -1.
|
||||
* copied from lines 177:181
|
||||
* resolves this case, but may cause other issues?
|
||||
*/
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2;
|
||||
int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2;
|
||||
actFireVector(actor, 0, 0, dx, dy, height2-height, kVectorBoneelBite);
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2;
|
||||
int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2;
|
||||
actFireVector(actor, 0, 0, dx, dy, height2 - height, kVectorBoneelBite);
|
||||
}
|
||||
|
||||
static void eelThinkTarget(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D* pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
aiNewState(actor, &eelTurn);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER *pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x-pSprite->x;
|
||||
int dy = y-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D* pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
aiNewState(actor, &eelTurn);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER* pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x - pSprite->x;
|
||||
int dy = y - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void eelThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
eelThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
eelThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void eelThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &eelSearch);
|
||||
eelThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &eelSearch);
|
||||
eelThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void eelThinkPonder(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2;
|
||||
int height2 = (getDudeInfo(pTarget->type)->eyeHeight*pTarget->yrepeat)<<2;
|
||||
int 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))
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (height2-height < -0x2000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2-height > 0xccc && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeDown);
|
||||
else if (height2-height < 0xccc && nDist < 0x399 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2-height > 0xccc && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeDown);
|
||||
else if (height2-height < -0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2-height < -0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2-height > 0xccc)
|
||||
aiNewState(actor, &eelDodgeDown);
|
||||
else
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
aiNewState(actor, &eelGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
|
||||
int height2 = (getDudeInfo(pTarget->type)->eyeHeight * pTarget->yrepeat) << 2;
|
||||
int 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))
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (height2 - height < -0x2000 && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2 - height > 0xccc && nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeDown);
|
||||
else if (height2 - height < 0xccc && nDist < 0x399 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2 - height > 0xccc && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeDown);
|
||||
else if (height2 - height < -0x2000 && nDist < 0x1400 && nDist > 0x800 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2 - height < -0x2000 && abs(nDeltaAngle) < 85 && nDist > 0x1400)
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
else if (height2 - height > 0xccc)
|
||||
aiNewState(actor, &eelDodgeDown);
|
||||
else
|
||||
aiNewState(actor, &eelDodgeUp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
aiNewState(actor, &eelGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void eelMoveDodgeUp(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x8000;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x8000;
|
||||
}
|
||||
|
||||
static void eelMoveDodgeDown(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
if (pXSprite->dodgeDir == 0)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
if (pXSprite->dodgeDir == 0)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int dx = actor->xvel();
|
||||
int dy = actor->yvel();
|
||||
int t1 = DMulScale(dx, nCos, dy, nSin, 30);
|
||||
int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
|
||||
if (pXSprite->dodgeDir > 0)
|
||||
t2 += pDudeInfo->sideSpeed;
|
||||
else
|
||||
t2 -= pDudeInfo->sideSpeed;
|
||||
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x44444;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x44444;
|
||||
}
|
||||
|
||||
static void eelThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &eelGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat)<<2;
|
||||
int top, bottom;
|
||||
GetActorExtents(actor, &top, &bottom);
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x399 && top2 > top && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelSwoop);
|
||||
else if (nDist <= 0x399 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelBite);
|
||||
else if (bottom2 > top && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelSwoop);
|
||||
else if (top2 < top && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelFly);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &eelGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &eelSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
|
||||
int top, bottom;
|
||||
GetActorExtents(actor, &top, &bottom);
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x399 && top2 > top && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelSwoop);
|
||||
else if (nDist <= 0x399 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelBite);
|
||||
else if (bottom2 > top && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelSwoop);
|
||||
else if (top2 < top && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &eelFly);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &eelSearch);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &eelSearch);
|
||||
}
|
||||
|
||||
static void eelMoveForward(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<26)/120)/120)<<2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang+256)&2047;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= 0x399)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 26) / 120) / 120) << 2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang + 256) & 2047;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= 0x399)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
}
|
||||
|
||||
static void eelMoveSwoop(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<26)/120)/120)<<2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x8000) && nDist <= 0x399)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x22222;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 26) / 120) / 120) << 2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x8000) && nDist <= 0x399)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = 0x22222;
|
||||
}
|
||||
|
||||
static void eelMoveAscend(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<26)/120)/120)<<2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x399)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x8000;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 26) / 120) / 120) << 2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x399)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -0x8000;
|
||||
}
|
||||
|
||||
void eelMoveToCeil(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = pSprite->z;
|
||||
int nSector = pSprite->sectnum;
|
||||
if (z - pXSprite->targetZ < 0x1000)
|
||||
{
|
||||
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats;
|
||||
pDudeExtraE->active = 0;
|
||||
pSprite->flags = 0;
|
||||
aiNewState(actor, &eelIdle);
|
||||
}
|
||||
else
|
||||
aiSetTarget(actor, x, y, sector[nSector].ceilingz);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = pSprite->z;
|
||||
int nSector = pSprite->sectnum;
|
||||
if (z - pXSprite->targetZ < 0x1000)
|
||||
{
|
||||
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
|
||||
pDudeExtraE->active = 0;
|
||||
pSprite->flags = 0;
|
||||
aiNewState(actor, &eelIdle);
|
||||
}
|
||||
else
|
||||
aiSetTarget(actor, x, y, sector[nSector].ceilingz);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -77,197 +77,197 @@ void BurnSeqCallback(int, DBloodActor*)
|
|||
|
||||
static void burnThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void burnThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnSearch);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnSearch);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnSearch);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnSearch);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnSearch);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnSearch);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnSearch);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnSearch);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void burnThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnGoto);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnGoto);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnGoto);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnGoto);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnGoto);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnGoto);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnGoto);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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 kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnSearch);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnSearch);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnSearch);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnSearch);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
if (nDist < 0x333 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnAttack);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnAttack);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnAttack);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnAttack);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnAttack);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnAttack);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnGoto);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnGoto);
|
||||
break;
|
||||
case 242:
|
||||
aiNewState(actor, &zombieFBurnGoto);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnGoto);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnGoto);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnGoto);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
actor->SetTarget(nullptr);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnGoto);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnGoto);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnGoto);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnGoto);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnGoto);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnGoto);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnGoto);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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 kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnSearch);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnSearch);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnSearch);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnSearch);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnSearch);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
if (nDist < 0x333 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnAttack);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnAttack);
|
||||
break;
|
||||
case kDudeBurningZombieButcher:
|
||||
aiNewState(actor, &zombieFBurnAttack);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnAttack);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnAttack);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnAttack);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudeBurningCultist:
|
||||
aiNewState(actor, &cultistBurnGoto);
|
||||
break;
|
||||
case kDudeBurningZombieAxe:
|
||||
aiNewState(actor, &zombieABurnGoto);
|
||||
break;
|
||||
case 242:
|
||||
aiNewState(actor, &zombieFBurnGoto);
|
||||
break;
|
||||
case kDudeBurningInnocent:
|
||||
aiNewState(actor, &innocentBurnGoto);
|
||||
break;
|
||||
case kDudeBurningBeast:
|
||||
aiNewState(actor, &beastBurnGoto);
|
||||
break;
|
||||
case kDudeBurningTinyCaleb:
|
||||
aiNewState(actor, &tinycalebBurnGoto);
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
aiNewState(actor, &genDudeBurnSearch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,14 +30,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void calebThinkSearch(DBloodActor *);
|
||||
static void calebThinkGoto(DBloodActor *);
|
||||
static void calebThinkChase(DBloodActor *);
|
||||
static void calebThinkSwimGoto(DBloodActor *);
|
||||
static void calebThinkSwimChase(DBloodActor *);
|
||||
static void sub_65D04(DBloodActor *);
|
||||
static void sub_65F44(DBloodActor *);
|
||||
static void sub_661E0(DBloodActor *);
|
||||
static void calebThinkSearch(DBloodActor*);
|
||||
static void calebThinkGoto(DBloodActor*);
|
||||
static void calebThinkChase(DBloodActor*);
|
||||
static void calebThinkSwimGoto(DBloodActor*);
|
||||
static void calebThinkSwimChase(DBloodActor*);
|
||||
static void sub_65D04(DBloodActor*);
|
||||
static void sub_65F44(DBloodActor*);
|
||||
static void sub_661E0(DBloodActor*);
|
||||
|
||||
AISTATE tinycalebIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, 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)
|
||||
{
|
||||
spritetype *pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
int dz = actor->dudeSlope;
|
||||
dx += Random2(1500);
|
||||
dy += Random2(1500);
|
||||
dz += Random2(1500);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
int r1 = Random3(500);
|
||||
int r2 = Random3(1000);
|
||||
int r3 = Random3(1000);
|
||||
actFireVector(actor, 0, 0, dx+r3, dy+r2, dz+r1, kVectorShell);
|
||||
}
|
||||
if (Chance(0x8000))
|
||||
sfxPlay3DSound(actor, 10000+Random(5), -1, 0);
|
||||
if (Chance(0x8000))
|
||||
sfxPlay3DSound(actor, 1001, -1, 0);
|
||||
else
|
||||
sfxPlay3DSound(actor, 1002, -1, 0);
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
int dz = actor->dudeSlope;
|
||||
dx += Random2(1500);
|
||||
dy += Random2(1500);
|
||||
dz += Random2(1500);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
int r1 = Random3(500);
|
||||
int r2 = Random3(1000);
|
||||
int r3 = Random3(1000);
|
||||
actFireVector(actor, 0, 0, dx + r3, dy + r2, dz + r1, kVectorShell);
|
||||
}
|
||||
if (Chance(0x8000))
|
||||
sfxPlay3DSound(actor, 10000 + Random(5), -1, 0);
|
||||
if (Chance(0x8000))
|
||||
sfxPlay3DSound(actor, 1001, -1, 0);
|
||||
else
|
||||
sfxPlay3DSound(actor, 1002, -1, 0);
|
||||
}
|
||||
|
||||
static void calebThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void calebThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void calebThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
{
|
||||
aiPlay3DSound(actor, 11000+Random(4), AI_SFX_PRIORITY_1, -1);
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
actor->dudeSlope = DivScale(pTarget->z-pSprite->z, nDist, 10);
|
||||
if (nDist < 0x599 && abs(nDeltaAngle) < 28)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycalebAttack);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycalebAttack);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimDodge);
|
||||
else
|
||||
aiNewState(actor, &tinycalebDodge);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycalebAttack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
{
|
||||
aiPlay3DSound(actor, 11000 + Random(4), AI_SFX_PRIORITY_1, -1);
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &tinycalebSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
actor->dudeSlope = DivScale(pTarget->z - pSprite->z, nDist, 10);
|
||||
if (nDist < 0x599 && abs(nDeltaAngle) < 28)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycalebAttack);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycalebAttack);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimDodge);
|
||||
else
|
||||
aiNewState(actor, &tinycalebDodge);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycalebAttack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimGoto);
|
||||
else
|
||||
aiNewState(actor, &tinycalebGoto);
|
||||
if (Chance(0x2000))
|
||||
sfxPlay3DSound(actor, 10000 + Random(5), -1, 0);
|
||||
actor->SetTarget(nullptr);
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &tinycalebSwimGoto);
|
||||
else
|
||||
aiNewState(actor, &tinycalebGoto);
|
||||
if (Chance(0x2000))
|
||||
sfxPlay3DSound(actor, 10000 + Random(5), -1, 0);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void calebThinkSwimGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void calebThinkSwimChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &tinycalebSwimGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
int height = pDudeInfo->eyeHeight+pSprite->z;
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycaleb13967C);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
aiNewState(actor, &tinycalebSwimGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &tinycalebSwimGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &tinycalebSwimSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int height = pDudeInfo->eyeHeight + pSprite->z;
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tinycalebSwimAttack);
|
||||
else
|
||||
aiNewState(actor, &tinycaleb13967C);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
aiNewState(actor, &tinycalebSwimGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void sub_65D04(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = pDudeInfo->frontSpeed<<2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang+256)&2047;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Random(64) < 32 && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel>>2;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = pDudeInfo->frontSpeed << 2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang + 256) & 2047;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Random(64) < 32 && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel >> 2;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
}
|
||||
|
||||
static void sub_65F44(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = pDudeInfo->frontSpeed<<2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pXSprite->goalAng = (pSprite->ang+512)&2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int dz = z2 - z;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x600) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -dz;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = pDudeInfo->frontSpeed << 2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pXSprite->goalAng = (pSprite->ang + 512) & 2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int dz = z2 - z;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x600) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -dz;
|
||||
}
|
||||
|
||||
static void sub_661E0(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = pDudeInfo->frontSpeed<<2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pSprite->ang = (pSprite->ang+512)&2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int dz = (z2 - z)<<3;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = dz;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = pDudeInfo->frontSpeed << 2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pSprite->ang = (pSprite->ang + 512) & 2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int dz = (z2 - z) << 3;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = dz;
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,10 +30,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void cerberusThinkSearch(DBloodActor *actor);
|
||||
static void cerberusThinkTarget(DBloodActor *actor);
|
||||
static void cerberusThinkGoto(DBloodActor *actor);
|
||||
static void cerberusThinkChase(DBloodActor *actor);
|
||||
static void cerberusThinkSearch(DBloodActor* actor);
|
||||
static void cerberusThinkTarget(DBloodActor* actor);
|
||||
static void cerberusThinkGoto(DBloodActor* actor);
|
||||
static void cerberusThinkChase(DBloodActor* actor);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype *pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
///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;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int dz = pTarget->z-pSprite->z;
|
||||
actFireVector(actor, 350, -100, dx, dy, dz, kVectorCerberusHack);
|
||||
actFireVector(actor, -350, 0, dx, dy, dz, kVectorCerberusHack);
|
||||
actFireVector(actor, 0, 0, dx, dy, dz, kVectorCerberusHack);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
///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;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int dz = pTarget->z - pSprite->z;
|
||||
actFireVector(actor, 350, -100, dx, dy, dz, kVectorCerberusHack);
|
||||
actFireVector(actor, -350, 0, dx, dy, dz, kVectorCerberusHack);
|
||||
actFireVector(actor, 0, 0, dx, dy, dz, kVectorCerberusHack);
|
||||
}
|
||||
|
||||
void cerberusBurnSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pDudeInfo->eyeHeight*pSprite->yrepeat;
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pDudeInfo->eyeHeight * pSprite->yrepeat;
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height; // ???
|
||||
TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa };
|
||||
Aim aim;
|
||||
aim.dx = CosScale16(pSprite->ang);
|
||||
aim.dy = SinScale16(pSprite->ang);
|
||||
aim.dz = actor->dudeSlope;
|
||||
int nClosest = 0x7fffffff;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype *pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags&8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2-x, y2-y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt1.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt1.at10, 12);
|
||||
x2 += (actor2->xvel() * t) >> 12;
|
||||
y2 += (actor2->yvel() * t) >> 12;
|
||||
z2 += (actor2->zvel() * t) >> 8;
|
||||
}
|
||||
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z+MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetSpriteExtents(pSprite2, &top, &bottom);
|
||||
if (tz-tsr > bottom || tz+tsr < top)
|
||||
continue;
|
||||
int dx = (tx-x2)>>4;
|
||||
int dy = (ty-y2)>>4;
|
||||
int dz = (tz-z2)>>8;
|
||||
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2-x, y2-y);
|
||||
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024;
|
||||
if (abs(nDeltaAngle) <= tt1.at8)
|
||||
{
|
||||
int tz = pSprite2->z-pSprite->z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
aim.dz = tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
|
||||
break;
|
||||
}
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height; // ???
|
||||
TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa };
|
||||
Aim aim;
|
||||
aim.dx = CosScale16(pSprite->ang);
|
||||
aim.dy = SinScale16(pSprite->ang);
|
||||
aim.dz = actor->dudeSlope;
|
||||
int nClosest = 0x7fffffff;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype* pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags & 8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2 - x, y2 - y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt1.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt1.at10, 12);
|
||||
x2 += (actor2->xvel() * t) >> 12;
|
||||
y2 += (actor2->yvel() * t) >> 12;
|
||||
z2 += (actor2->zvel() * t) >> 8;
|
||||
}
|
||||
int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z + MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetSpriteExtents(pSprite2, &top, &bottom);
|
||||
if (tz - tsr > bottom || tz + tsr < top)
|
||||
continue;
|
||||
int dx = (tx - x2) >> 4;
|
||||
int dy = (ty - y2) >> 4;
|
||||
int dz = (tz - z2) >> 8;
|
||||
int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2 - x, y2 - y);
|
||||
int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
|
||||
if (abs(nDeltaAngle) <= tt1.at8)
|
||||
{
|
||||
int tz = pSprite2->z - pSprite->z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
aim.dz = tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cerberusBurnSeqCallback2(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pDudeInfo->eyeHeight*pSprite->yrepeat;
|
||||
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height; // ???
|
||||
TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa };
|
||||
Aim aim;
|
||||
int ax, ay, az;
|
||||
aim.dx = ax = CosScale16(pSprite->ang);
|
||||
aim.dy = ay = SinScale16(pSprite->ang);
|
||||
aim.dz = actor->dudeSlope;
|
||||
az = 0;
|
||||
int nClosest = 0x7fffffff;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype *pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags&8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2-x, y2-y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt1.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt1.at10, 12);
|
||||
x2 += (actor->xvel() * t) >> 12;
|
||||
y2 += (actor->yvel() * t) >> 12;
|
||||
z2 += (actor->zvel() * t) >> 8;
|
||||
}
|
||||
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z+MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetActorExtents(actor2, &top, &bottom);
|
||||
if (tz-tsr > bottom || tz+tsr < top)
|
||||
continue;
|
||||
int dx = (tx-x2)>>4;
|
||||
int dy = (ty-y2)>>4;
|
||||
int dz = (tz-z2)>>8;
|
||||
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2-x, y2-y);
|
||||
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024;
|
||||
if (abs(nDeltaAngle) <= tt1.at8)
|
||||
{
|
||||
DUDEINFO *pDudeInfo2 = getDudeInfo(pSprite2->type);
|
||||
int height = (pDudeInfo2->aimHeight*pSprite2->yrepeat)<<2;
|
||||
int tz = (z2-height)-z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
aim.dz = tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
|
||||
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFlameHound);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
|
||||
break;
|
||||
}
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pDudeInfo->eyeHeight * pSprite->yrepeat;
|
||||
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height; // ???
|
||||
TARGETTRACK tt1 = { 0x10000, 0x10000, 0x100, 0x55, 0x1aaaaa };
|
||||
Aim aim;
|
||||
int ax, ay, az;
|
||||
aim.dx = ax = CosScale16(pSprite->ang);
|
||||
aim.dy = ay = SinScale16(pSprite->ang);
|
||||
aim.dz = actor->dudeSlope;
|
||||
az = 0;
|
||||
int nClosest = 0x7fffffff;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype* pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags & 8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2 - x, y2 - y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt1.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt1.at10, 12);
|
||||
x2 += (actor->xvel() * t) >> 12;
|
||||
y2 += (actor->yvel() * t) >> 12;
|
||||
z2 += (actor->zvel() * t) >> 8;
|
||||
}
|
||||
int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z + MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetActorExtents(actor2, &top, &bottom);
|
||||
if (tz - tsr > bottom || tz + tsr < top)
|
||||
continue;
|
||||
int dx = (tx - x2) >> 4;
|
||||
int dy = (ty - y2) >> 4;
|
||||
int dz = (tz - z2) >> 8;
|
||||
int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2 - x, y2 - y);
|
||||
int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
|
||||
if (abs(nDeltaAngle) <= tt1.at8)
|
||||
{
|
||||
DUDEINFO* pDudeInfo2 = getDudeInfo(pSprite2->type);
|
||||
int height = (pDudeInfo2->aimHeight * pSprite2->yrepeat) << 2;
|
||||
int tz = (z2 - height) - z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
aim.dz = tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
|
||||
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFlameHound);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cerberusThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void cerberusThinkTarget(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D* pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
if (pSprite->type == kDudeCerberusTwoHead)
|
||||
aiNewState(actor, &cerberus139890);
|
||||
else
|
||||
aiNewState(actor, &cerberus1398AC);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER *pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x-pSprite->x;
|
||||
int dy = y-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D* pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
if (pSprite->type == kDudeCerberusTwoHead)
|
||||
aiNewState(actor, &cerberus139890);
|
||||
else
|
||||
aiNewState(actor, &cerberus1398AC);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER* pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x - pSprite->x;
|
||||
int dy = y - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cerberusThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusSearch);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Search);
|
||||
break;
|
||||
}
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusSearch);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Search);
|
||||
break;
|
||||
}
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void cerberusThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr) {
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusGoto);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Goto);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr) {
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusGoto);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Goto);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) {
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusSearch);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Search);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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));
|
||||
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
|
||||
if (nDist < 0x1b00 && nDist > 0xd00 && abs(nDeltaAngle) < 85) {
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusBurn);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Burn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pXTarget->health == 0) {
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusSearch);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Search);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0) {
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusSearch);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Search);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pSprite->type) {
|
||||
case kDudeCerberusTwoHead:
|
||||
aiNewState(actor, &cerberusGoto);
|
||||
break;
|
||||
case kDudeCerberusOneHead:
|
||||
aiNewState(actor, &cerberus2Goto);
|
||||
break;
|
||||
}
|
||||
actor->SetTarget(nullptr);
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
|
||||
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
|
||||
|
|
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
|
@ -30,14 +30,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void gillThinkSearch(DBloodActor *);
|
||||
static void gillThinkGoto(DBloodActor *);
|
||||
static void gillThinkChase(DBloodActor *);
|
||||
static void gillThinkSwimGoto(DBloodActor *);
|
||||
static void gillThinkSwimChase(DBloodActor *);
|
||||
static void sub_6CB00(DBloodActor *);
|
||||
static void sub_6CD74(DBloodActor *);
|
||||
static void sub_6D03C(DBloodActor *);
|
||||
static void gillThinkSearch(DBloodActor*);
|
||||
static void gillThinkGoto(DBloodActor*);
|
||||
static void gillThinkChase(DBloodActor*);
|
||||
static void gillThinkSwimGoto(DBloodActor*);
|
||||
static void gillThinkSwimChase(DBloodActor*);
|
||||
static void sub_6CB00(DBloodActor*);
|
||||
static void sub_6CD74(DBloodActor*);
|
||||
static void sub_6D03C(DBloodActor*);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
int dz = pSprite->z-pTarget->z;
|
||||
dx += 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);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
int dz = pSprite->z - pTarget->z;
|
||||
dx += 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);
|
||||
}
|
||||
|
||||
static void gillThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void gillThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void gillThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
actor->dudeSlope = DivScale(pTarget->z-pSprite->z, nDist, 10);
|
||||
if (nDist < 921 && abs(nDeltaAngle) < 28)
|
||||
{
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
aiNewState(actor, &gillBeastBite);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
aiNewState(actor, &gillBeastBite);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimDodge);
|
||||
else
|
||||
aiNewState(actor, &gillBeastDodge);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
aiNewState(actor, &gillBeastBite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
else
|
||||
aiNewState(actor, &gillBeastSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
actor->dudeSlope = DivScale(pTarget->z - pSprite->z, nDist, 10);
|
||||
if (nDist < 921 && abs(nDeltaAngle) < 28)
|
||||
{
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
aiNewState(actor, &gillBeastBite);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
aiNewState(actor, &gillBeastBite);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimDodge);
|
||||
else
|
||||
aiNewState(actor, &gillBeastDodge);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
aiNewState(actor, &gillBeastBite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
XSECTOR *pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimGoto);
|
||||
else
|
||||
aiNewState(actor, &gillBeastGoto);
|
||||
sfxPlay3DSound(actor, 1701, -1, 0);
|
||||
actor->SetTarget(nullptr);
|
||||
XSECTOR* pXSector;
|
||||
int nXSector = sector[pSprite->sectnum].extra;
|
||||
if (nXSector > 0)
|
||||
pXSector = &xsector[nXSector];
|
||||
else
|
||||
pXSector = NULL;
|
||||
if (pXSector && pXSector->Underwater)
|
||||
aiNewState(actor, &gillBeastSwimGoto);
|
||||
else
|
||||
aiNewState(actor, &gillBeastGoto);
|
||||
sfxPlay3DSound(actor, 1701, -1, 0);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void gillThinkSwimGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void gillThinkSwimChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
int height = pDudeInfo->eyeHeight+pSprite->z;
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
{
|
||||
aiPlay3DSound(actor, 1700, AI_SFX_PRIORITY_1, -1);
|
||||
aiNewState(actor, &gillBeast13A154);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
aiNewState(actor, &gillBeast13A154);
|
||||
return;
|
||||
}
|
||||
aiNewState(actor, &gillBeastSwimGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &gillBeastSwimSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int height = pDudeInfo->eyeHeight + pSprite->z;
|
||||
int 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 (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &gillBeastSwimBite);
|
||||
else
|
||||
{
|
||||
aiPlay3DSound(actor, 1700, AI_SFX_PRIORITY_1, -1);
|
||||
aiNewState(actor, &gillBeast13A154);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
aiNewState(actor, &gillBeast13A154);
|
||||
return;
|
||||
}
|
||||
aiNewState(actor, &gillBeastSwimGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void sub_6CB00(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
int nSprite = pSprite->index;
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<27)/120)/120)<<2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang+256)&2047;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Random(64) < 32 && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel>>2;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
int nSprite = pSprite->index;
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 27) / 120) / 120) << 2;
|
||||
if (abs(nAng) > 341)
|
||||
return;
|
||||
if (actor->GetTarget() == nullptr)
|
||||
pSprite->ang = (pSprite->ang + 256) & 2047;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Random(64) < 32 && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
if (actor->GetTarget() == nullptr)
|
||||
t1 += nAccel;
|
||||
else
|
||||
t1 += nAccel >> 2;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
}
|
||||
|
||||
static void sub_6CD74(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<27)/120)/120)<<2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pXSprite->goalAng = (pSprite->ang+512)&2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int dz = z2 - z;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x600) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -dz;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 27) / 120) / 120) << 2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pXSprite->goalAng = (pSprite->ang + 512) & 2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int dz = z2 - z;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x600) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = -dz;
|
||||
}
|
||||
|
||||
static void sub_6D03C(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng+1024-pSprite->ang)&2047)-1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed<<2)>>4;
|
||||
pSprite->ang = (pSprite->ang+ClipRange(nAng, -nTurnRange, nTurnRange))&2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed-(((4-gGameOptions.nDifficulty)<<27)/120)/120)<<2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pSprite->ang = (pSprite->ang+512)&2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int dz = (z2 - z)<<3;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel>>1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = dz;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
int z = pSprite->z + getDudeInfo(pSprite->type)->eyeHeight;
|
||||
int z2 = pTarget->z + getDudeInfo(pTarget->type)->eyeHeight;
|
||||
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
|
||||
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
|
||||
int nAccel = (pDudeInfo->frontSpeed - (((4 - gGameOptions.nDifficulty) << 27) / 120) / 120) << 2;
|
||||
if (abs(nAng) > 341)
|
||||
{
|
||||
pSprite->ang = (pSprite->ang + 512) & 2047;
|
||||
return;
|
||||
}
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int dz = (z2 - z) << 3;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (Chance(0x4000) && nDist <= 0x400)
|
||||
return;
|
||||
int nCos = Cos(pSprite->ang);
|
||||
int nSin = Sin(pSprite->ang);
|
||||
int vx = actor->xvel();
|
||||
int vy = actor->yvel();
|
||||
int t1 = DMulScale(vx, nCos, vy, nSin, 30);
|
||||
int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
|
||||
t1 += nAccel >> 1;
|
||||
actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30);
|
||||
actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30);
|
||||
actor->zvel() = dz;
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void handThinkSearch(DBloodActor *);
|
||||
static void handThinkGoto(DBloodActor *);
|
||||
static void handThinkChase(DBloodActor *);
|
||||
static void handThinkSearch(DBloodActor*);
|
||||
static void handThinkGoto(DBloodActor*);
|
||||
static void handThinkChase(DBloodActor*);
|
||||
|
||||
AISTATE handIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, 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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
if (IsPlayerSprite(pTarget))
|
||||
{
|
||||
PLAYER *pPlayer = &gPlayer[pTarget->type-kDudePlayer1];
|
||||
if (!pPlayer->hand)
|
||||
{
|
||||
pPlayer->hand = 1;
|
||||
actPostSprite(actor, kStatFree);
|
||||
}
|
||||
}
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
if (IsPlayerSprite(pTarget))
|
||||
{
|
||||
PLAYER* pPlayer = &gPlayer[pTarget->type - kDudePlayer1];
|
||||
if (!pPlayer->hand)
|
||||
{
|
||||
pPlayer->hand = 1;
|
||||
actPostSprite(actor, kStatFree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void handThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &handSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &handSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void handThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &handGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &handSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &handSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
if (nDist < 0x233 && abs(nDeltaAngle) < 85 && gGameOptions.nGameType == 0)
|
||||
aiNewState(actor, &handJump);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &handGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &handSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &handSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
if (nDist < 0x233 && abs(nDeltaAngle) < 85 && gGameOptions.nGameType == 0)
|
||||
aiNewState(actor, &handJump);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &handGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &handGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void houndThinkSearch(DBloodActor *);
|
||||
static void houndThinkGoto(DBloodActor *);
|
||||
static void houndThinkChase(DBloodActor *);
|
||||
static void houndThinkSearch(DBloodActor*);
|
||||
static void houndThinkGoto(DBloodActor*);
|
||||
static void houndThinkChase(DBloodActor*);
|
||||
|
||||
AISTATE houndIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
///assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
|
||||
Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
|
||||
return;
|
||||
}
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
///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;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (IsPlayerSprite(pTarget) || gModernMap) // allow to hit non-player targets
|
||||
actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite);
|
||||
#else
|
||||
if (IsPlayerSprite(pTarget))
|
||||
actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite);
|
||||
#endif
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (IsPlayerSprite(pTarget) || gModernMap) // allow to hit non-player targets
|
||||
actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite);
|
||||
#else
|
||||
if (IsPlayerSprite(pTarget))
|
||||
actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorHoundBite);
|
||||
#endif
|
||||
}
|
||||
|
||||
void houndBurnSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
spritetype* pSprite = &actor->s();
|
||||
actFireMissile(pSprite, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFlameHound);
|
||||
spritetype* pSprite = &actor->s();
|
||||
actFireMissile(pSprite, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFlameHound);
|
||||
}
|
||||
|
||||
static void houndThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void houndThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &houndSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &houndSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void houndThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &houndGoto);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &houndSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &houndSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &houndBurn);
|
||||
else if(nDist < 0x266 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &houndBite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &houndGoto);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &houndSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &houndSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &houndBurn);
|
||||
else if (nDist < 0x266 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &houndBite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &houndGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &houndGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void innocThinkSearch(DBloodActor *);
|
||||
static void innocThinkGoto(DBloodActor *);
|
||||
static void innocThinkChase(DBloodActor *);
|
||||
static void innocThinkSearch(DBloodActor*);
|
||||
static void innocThinkGoto(DBloodActor*);
|
||||
static void innocThinkChase(DBloodActor*);
|
||||
|
||||
AISTATE innocentIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
|
||||
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)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void innocThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &innocentSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &innocentSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void innocThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &innocentGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &innocentSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget))
|
||||
{
|
||||
aiNewState(actor, &innocentSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
if (nDist < 0x666 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &innocentIdle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &innocentGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &innocentSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget))
|
||||
{
|
||||
aiNewState(actor, &innocentSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
if (nDist < 0x666 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &innocentIdle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiPlay3DSound(actor, 7000+Random(6), AI_SFX_PRIORITY_1, -1);
|
||||
aiNewState(actor, &innocentGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
aiPlay3DSound(actor, 7000 + Random(6), AI_SFX_PRIORITY_1, -1);
|
||||
aiNewState(actor, &innocentGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -53,202 +53,202 @@ AISTATE tentacleChase = { kAiStateChase, 6, -1, 0, NULL, aiMoveTurn, aiPodChase,
|
|||
|
||||
void sub_6FF08(int, DBloodActor* actor)
|
||||
{
|
||||
sfxPlay3DSound(actor, 2503, -1, 0);
|
||||
sfxPlay3DSound(actor, 2503, -1, 0);
|
||||
}
|
||||
|
||||
void sub_6FF54(int, DBloodActor* actor)
|
||||
{
|
||||
sfxPlay3DSound(actor, 2500, -1, 0);
|
||||
sfxPlay3DSound(actor, 2500, -1, 0);
|
||||
}
|
||||
|
||||
void podAttack(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int x = pTarget->x-pSprite->x;
|
||||
int y = pTarget->y-pSprite->y;
|
||||
int dz = pTarget->z-pSprite->z;
|
||||
x += Random2(1000);
|
||||
y += Random2(1000);
|
||||
int nDist = approxDist(x, y);
|
||||
int nDist2 = nDist / 540;
|
||||
DBloodActor* pMissile = nullptr;
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudePodGreen:
|
||||
dz += 8000;
|
||||
if (pDudeInfo->seeDist*0.1 < nDist)
|
||||
{
|
||||
if (Chance(0x8000))
|
||||
sfxPlay3DSound(actor, 2474, -1, 0);
|
||||
else
|
||||
sfxPlay3DSound(actor, 2475, -1, 0);
|
||||
pMissile = actFireThing(actor, 0, -8000, dz/128-14500, kThingPodGreenBall, (nDist2<<23)/120);
|
||||
}
|
||||
if (pMissile)
|
||||
seqSpawn(68, pMissile, -1);
|
||||
break;
|
||||
case kDudePodFire:
|
||||
dz += 8000;
|
||||
if (pDudeInfo->seeDist*0.1 < nDist)
|
||||
{
|
||||
sfxPlay3DSound(actor, 2454, -1, 0);
|
||||
pMissile = actFireThing(actor, 0, -8000, dz/128-14500, kThingPodFireBall, (nDist2<<23)/120);
|
||||
}
|
||||
if (pMissile)
|
||||
seqSpawn(22, pMissile, -1);
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
sub_746D4(pSprite, 240);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int x = pTarget->x - pSprite->x;
|
||||
int y = pTarget->y - pSprite->y;
|
||||
int dz = pTarget->z - pSprite->z;
|
||||
x += Random2(1000);
|
||||
y += Random2(1000);
|
||||
int nDist = approxDist(x, y);
|
||||
int nDist2 = nDist / 540;
|
||||
DBloodActor* pMissile = nullptr;
|
||||
switch (pSprite->type)
|
||||
{
|
||||
case kDudePodGreen:
|
||||
dz += 8000;
|
||||
if (pDudeInfo->seeDist * 0.1 < nDist)
|
||||
{
|
||||
if (Chance(0x8000))
|
||||
sfxPlay3DSound(actor, 2474, -1, 0);
|
||||
else
|
||||
sfxPlay3DSound(actor, 2475, -1, 0);
|
||||
pMissile = actFireThing(actor, 0, -8000, dz / 128 - 14500, kThingPodGreenBall, (nDist2 << 23) / 120);
|
||||
}
|
||||
if (pMissile)
|
||||
seqSpawn(68, pMissile, -1);
|
||||
break;
|
||||
case kDudePodFire:
|
||||
dz += 8000;
|
||||
if (pDudeInfo->seeDist * 0.1 < nDist)
|
||||
{
|
||||
sfxPlay3DSound(actor, 2454, -1, 0);
|
||||
pMissile = actFireThing(actor, 0, -8000, dz / 128 - 14500, kThingPodFireBall, (nDist2 << 23) / 120);
|
||||
}
|
||||
if (pMissile)
|
||||
seqSpawn(22, pMissile, -1);
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
sub_746D4(pSprite, 240);
|
||||
}
|
||||
|
||||
void sub_70284(int, DBloodActor* actor)
|
||||
{
|
||||
auto pSprite = &actor->s();
|
||||
sfxPlay3DSound(actor, 2502, -1, 0);
|
||||
int nDist, nBurn;
|
||||
DAMAGE_TYPE dmgType;
|
||||
switch (pSprite->type) {
|
||||
case kDudeTentacleGreen:
|
||||
default: // ???
|
||||
nBurn = 0;
|
||||
dmgType = kDamageBullet;
|
||||
nDist = 50;
|
||||
break;
|
||||
case kDudeTentacleFire: // ???
|
||||
nBurn = (gGameOptions.nDifficulty*120)>>2;
|
||||
dmgType = kDamageExplode;
|
||||
nDist = 75;
|
||||
break;
|
||||
}
|
||||
actRadiusDamage(actor, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, nDist, 1, 5*(1+gGameOptions.nDifficulty), dmgType, 2, nBurn);
|
||||
auto pSprite = &actor->s();
|
||||
sfxPlay3DSound(actor, 2502, -1, 0);
|
||||
int nDist, nBurn;
|
||||
DAMAGE_TYPE dmgType;
|
||||
switch (pSprite->type) {
|
||||
case kDudeTentacleGreen:
|
||||
default: // ???
|
||||
nBurn = 0;
|
||||
dmgType = kDamageBullet;
|
||||
nDist = 50;
|
||||
break;
|
||||
case kDudeTentacleFire: // ???
|
||||
nBurn = (gGameOptions.nDifficulty * 120) >> 2;
|
||||
dmgType = kDamageExplode;
|
||||
nDist = 75;
|
||||
break;
|
||||
}
|
||||
actRadiusDamage(actor, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, nDist, 1, 5 * (1 + gGameOptions.nDifficulty), dmgType, 2, nBurn);
|
||||
}
|
||||
|
||||
static void aiPodSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void aiPodMove(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) {
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podSearch);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleSearch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) {
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podSearch);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleSearch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void aiPodChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr) {
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podMove);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleMove);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
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 kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podSearch);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleSearch);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
if (abs(nDeltaAngle) < 85 && pTarget->type != kDudePodGreen && pTarget->type != kDudePodFire) {
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podStartChase);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleStartChase);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podMove);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleMove);
|
||||
break;
|
||||
}
|
||||
actor->SetTarget(nullptr);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr) {
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podMove);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleMove);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
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 kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podSearch);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleSearch);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
if (abs(nDeltaAngle) < 85 && pTarget->type != kDudePodGreen && pTarget->type != kDudePodFire) {
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podStartChase);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleStartChase);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (pSprite->type) {
|
||||
case kDudePodGreen:
|
||||
case kDudePodFire:
|
||||
aiNewState(actor, &podMove);
|
||||
break;
|
||||
case kDudeTentacleGreen:
|
||||
case kDudeTentacleFire:
|
||||
aiNewState(actor, &tentacleMove);
|
||||
break;
|
||||
}
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void ratThinkSearch(DBloodActor *);
|
||||
static void ratThinkGoto(DBloodActor *);
|
||||
static void ratThinkChase(DBloodActor *);
|
||||
static void ratThinkSearch(DBloodActor*);
|
||||
static void ratThinkGoto(DBloodActor*);
|
||||
static void ratThinkChase(DBloodActor*);
|
||||
|
||||
AISTATE ratIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL };
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
if (IsPlayerSprite(pTarget))
|
||||
actFireVector(actor, 0, 0, dx, dy, pTarget->z-pSprite->z, kVectorRatBite);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
if (IsPlayerSprite(pTarget))
|
||||
actFireVector(actor, 0, 0, dx, dy, pTarget->z - pSprite->z, kVectorRatBite);
|
||||
}
|
||||
|
||||
static void ratThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void ratThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &ratSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &ratSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void ratThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &ratGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &ratSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &ratSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
if (nDist < 0x399 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &ratBite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &ratGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &ratSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &ratSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
if (nDist < 0x399 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &ratBite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &ratGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &ratGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void spidThinkSearch(DBloodActor *);
|
||||
static void spidThinkGoto(DBloodActor *);
|
||||
static void spidThinkChase(DBloodActor *);
|
||||
static void spidThinkSearch(DBloodActor*);
|
||||
static void spidThinkGoto(DBloodActor*);
|
||||
static void spidThinkChase(DBloodActor*);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
spritetype *pDude = &dudeactor->s();
|
||||
if (IsPlayerSprite(pDude))
|
||||
{
|
||||
nBlind <<= 4;
|
||||
max <<= 4;
|
||||
PLAYER *pPlayer = &gPlayer[pDude->type-kDudePlayer1];
|
||||
if (pPlayer->blindEffect < max)
|
||||
{
|
||||
pPlayer->blindEffect = ClipHigh(pPlayer->blindEffect+nBlind, max);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
spritetype* pDude = &dudeactor->s();
|
||||
if (IsPlayerSprite(pDude))
|
||||
{
|
||||
nBlind <<= 4;
|
||||
max <<= 4;
|
||||
PLAYER* pPlayer = &gPlayer[pDude->type - kDudePlayer1];
|
||||
if (pPlayer->blindEffect < max)
|
||||
{
|
||||
pPlayer->blindEffect = ClipHigh(pPlayer->blindEffect + nBlind, max);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SpidBiteSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
dx += Random2(2000);
|
||||
dy += Random2(2000);
|
||||
int dz = Random2(2000);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
dx += Random2(2000);
|
||||
dy += Random2(2000);
|
||||
int dz = Random2(2000);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
|
||||
dx += Random2(2000);
|
||||
dy += Random2(2000);
|
||||
dz += Random2(2000);
|
||||
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
|
||||
spidBlindEffect(target, 8, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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);
|
||||
dy += Random2(2000);
|
||||
dz += Random2(2000);
|
||||
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
|
||||
spidBlindEffect(target, 8, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SpidJumpSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
dx += Random2(200);
|
||||
dy += Random2(200);
|
||||
int dz = Random2(200);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
if (IsPlayerSprite(pTarget)) {
|
||||
dz += pTarget->z-pSprite->z;
|
||||
switch (pSprite->type) {
|
||||
case kDudeSpiderBrown:
|
||||
case kDudeSpiderRed:
|
||||
case kDudeSpiderBlack:
|
||||
actor->xvel() = IntToFixed(dx);
|
||||
actor->yvel() = IntToFixed(dy);
|
||||
actor->zvel() = IntToFixed(dz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
int dx = CosScale16(pSprite->ang);
|
||||
int dy = SinScale16(pSprite->ang);
|
||||
dx += Random2(200);
|
||||
dy += Random2(200);
|
||||
int dz = Random2(200);
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
if (IsPlayerSprite(pTarget)) {
|
||||
dz += pTarget->z - pSprite->z;
|
||||
switch (pSprite->type) {
|
||||
case kDudeSpiderBrown:
|
||||
case kDudeSpiderRed:
|
||||
case kDudeSpiderBlack:
|
||||
actor->xvel() = IntToFixed(dx);
|
||||
actor->yvel() = IntToFixed(dy);
|
||||
actor->zvel() = IntToFixed(dz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpidBirthSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats;
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(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);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
|
||||
if (spawned)
|
||||
{
|
||||
pDudeExtraE->birthCounter++;
|
||||
spawned->SetOwner(spawned);
|
||||
gKillMgr.AddNewKill(1);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
pDudeExtraE->birthCounter++;
|
||||
spawned->SetOwner(spawned);
|
||||
gKillMgr.AddNewKill(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void spidThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void spidThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &spidSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &spidSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void spidThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &spidGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &spidSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &spidSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist) {
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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;
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &spidGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &spidSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &spidSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist) {
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
int height = (pDudeInfo->eyeHeight * pSprite->yrepeat) << 2;
|
||||
|
||||
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);
|
||||
actor->SetTarget(nullptr);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &spidGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,10 +30,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void sub_72580(DBloodActor *);
|
||||
static void sub_725A4(DBloodActor *);
|
||||
static void sub_72850(DBloodActor *);
|
||||
static void sub_72934(DBloodActor *);
|
||||
static void sub_72580(DBloodActor*);
|
||||
static void sub_725A4(DBloodActor*);
|
||||
static void sub_72850(DBloodActor*);
|
||||
static void sub_72934(DBloodActor*);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
XSPRITE* pXTarget = &actor->GetTarget()->x();
|
||||
int nTarget = pTarget->index;
|
||||
int nOwner = pSprite->owner;
|
||||
if (pXTarget->burnTime == 0)
|
||||
evPost(nTarget, 3, 0, kCallbackFXFlameLick);
|
||||
actBurnSprite(nOwner, pXTarget, 40);
|
||||
if (Chance(0x6000))
|
||||
aiNewState(actor, &tcherno13A9D4);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
XSPRITE* pXTarget = &actor->GetTarget()->x();
|
||||
int nTarget = pTarget->index;
|
||||
int nOwner = pSprite->owner;
|
||||
if (pXTarget->burnTime == 0)
|
||||
evPost(nTarget, 3, 0, kCallbackFXFlameLick);
|
||||
actBurnSprite(nOwner, pXTarget, 40);
|
||||
if (Chance(0x6000))
|
||||
aiNewState(actor, &tcherno13A9D4);
|
||||
}
|
||||
|
||||
void sub_71BD4(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pSprite->yrepeat*pDudeInfo->eyeHeight;
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height;
|
||||
TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 };
|
||||
Aim aim;
|
||||
aim.dx = CosScale16(pSprite->ang);
|
||||
aim.dy = SinScale16(pSprite->ang);
|
||||
aim.dz = actor->dudeSlope;
|
||||
int nClosest = 0x7fffffff;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype* pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags&8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2-x, y2-y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt.at10, 12);
|
||||
x2 += (actor->xvel() * t) >> 12;
|
||||
y2 += (actor->yvel() * t) >> 12;
|
||||
z2 += (actor->zvel() * t) >> 8;
|
||||
}
|
||||
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z+MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetSpriteExtents(pSprite2, &top, &bottom);
|
||||
if (tz-tsr > bottom || tz+tsr < top)
|
||||
continue;
|
||||
int dx = (tx-x2)>>4;
|
||||
int dy = (ty-y2)>>4;
|
||||
int dz = (tz-z2)>>8;
|
||||
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2-x, y2-y);
|
||||
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024;
|
||||
if (abs(nDeltaAngle) <= tt.at8)
|
||||
{
|
||||
int tz = pSprite2->z-pSprite->z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
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);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pSprite->yrepeat * pDudeInfo->eyeHeight;
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height;
|
||||
TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 };
|
||||
Aim aim;
|
||||
aim.dx = CosScale16(pSprite->ang);
|
||||
aim.dy = SinScale16(pSprite->ang);
|
||||
aim.dz = actor->dudeSlope;
|
||||
int nClosest = 0x7fffffff;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype* pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags & 8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2 - x, y2 - y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt.at10, 12);
|
||||
x2 += (actor->xvel() * t) >> 12;
|
||||
y2 += (actor->yvel() * t) >> 12;
|
||||
z2 += (actor->zvel() * t) >> 8;
|
||||
}
|
||||
int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z + MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetSpriteExtents(pSprite2, &top, &bottom);
|
||||
if (tz - tsr > bottom || tz + tsr < top)
|
||||
continue;
|
||||
int dx = (tx - x2) >> 4;
|
||||
int dy = (ty - y2) >> 4;
|
||||
int dz = (tz - z2) >> 8;
|
||||
int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2 - x, y2 - y);
|
||||
int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
|
||||
if (abs(nDeltaAngle) <= tt.at8)
|
||||
{
|
||||
int tz = pSprite2->z - pSprite->z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
void sub_720AC(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pSprite->yrepeat*pDudeInfo->eyeHeight;
|
||||
int ax, ay, az;
|
||||
ax = CosScale16(pSprite->ang);
|
||||
ay = SinScale16(pSprite->ang);
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height;
|
||||
TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 };
|
||||
Aim aim;
|
||||
aim.dx = ax;
|
||||
aim.dy = ay;
|
||||
aim.dz = actor->dudeSlope;
|
||||
int nClosest = 0x7fffffff;
|
||||
az = 0;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype* pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags&8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2-x, y2-y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt.at10, 12);
|
||||
x2 += (actor->xvel()*t)>>12;
|
||||
y2 += (actor->yvel()*t)>>12;
|
||||
z2 += (actor->zvel()*t)>>8;
|
||||
}
|
||||
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z+MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetSpriteExtents(pSprite2, &top, &bottom);
|
||||
if (tz-tsr > bottom || tz+tsr < top)
|
||||
continue;
|
||||
int dx = (tx-x2)>>4;
|
||||
int dy = (ty-y2)>>4;
|
||||
int dz = (tz-z2)>>8;
|
||||
int nDist2 = ksqrt(dx*dx+dy*dy+dz*dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2-x, y2-y);
|
||||
int nDeltaAngle = ((nAngle-pSprite->ang+1024)&2047)-1024;
|
||||
if (abs(nDeltaAngle) <= tt.at8)
|
||||
{
|
||||
int tz = pSprite2->z-pSprite->z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
aim.dz = tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, -aim.dz, kMissileFireballTchernobog);
|
||||
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFireballTchernobog);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = pSprite->yrepeat * pDudeInfo->eyeHeight;
|
||||
int ax, ay, az;
|
||||
ax = CosScale16(pSprite->ang);
|
||||
ay = SinScale16(pSprite->ang);
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = height;
|
||||
TARGETTRACK tt = { 0x10000, 0x10000, 0x100, 0x55, 0x100000 };
|
||||
Aim aim;
|
||||
aim.dx = ax;
|
||||
aim.dy = ay;
|
||||
aim.dz = actor->dudeSlope;
|
||||
int nClosest = 0x7fffffff;
|
||||
az = 0;
|
||||
BloodStatIterator it(kStatDude);
|
||||
while (auto actor2 = it.Next())
|
||||
{
|
||||
spritetype* pSprite2 = &actor2->s();
|
||||
if (pSprite == pSprite2 || !(pSprite2->flags & 8))
|
||||
continue;
|
||||
int x2 = pSprite2->x;
|
||||
int y2 = pSprite2->y;
|
||||
int z2 = pSprite2->z;
|
||||
int nDist = approxDist(x2 - x, y2 - y);
|
||||
if (nDist == 0 || nDist > 0x2800)
|
||||
continue;
|
||||
if (tt.at10)
|
||||
{
|
||||
int t = DivScale(nDist, tt.at10, 12);
|
||||
x2 += (actor->xvel() * t) >> 12;
|
||||
y2 += (actor->yvel() * t) >> 12;
|
||||
z2 += (actor->zvel() * t) >> 8;
|
||||
}
|
||||
int tx = x + MulScale(Cos(pSprite->ang), nDist, 30);
|
||||
int ty = y + MulScale(Sin(pSprite->ang), nDist, 30);
|
||||
int tz = z + MulScale(actor->dudeSlope, nDist, 10);
|
||||
int tsr = MulScale(9460, nDist, 10);
|
||||
int top, bottom;
|
||||
GetSpriteExtents(pSprite2, &top, &bottom);
|
||||
if (tz - tsr > bottom || tz + tsr < top)
|
||||
continue;
|
||||
int dx = (tx - x2) >> 4;
|
||||
int dy = (ty - y2) >> 4;
|
||||
int dz = (tz - z2) >> 8;
|
||||
int nDist2 = ksqrt(dx * dx + dy * dy + dz * dz);
|
||||
if (nDist2 < nClosest)
|
||||
{
|
||||
int nAngle = getangle(x2 - x, y2 - y);
|
||||
int nDeltaAngle = ((nAngle - pSprite->ang + 1024) & 2047) - 1024;
|
||||
if (abs(nDeltaAngle) <= tt.at8)
|
||||
{
|
||||
int tz = pSprite2->z - pSprite->z;
|
||||
if (cansee(x, y, z, pSprite->sectnum, x2, y2, z2, pSprite2->sectnum))
|
||||
{
|
||||
nClosest = nDist2;
|
||||
aim.dx = CosScale16(nAngle);
|
||||
aim.dy = SinScale16(nAngle);
|
||||
aim.dz = DivScale(tz, nDist, 10);
|
||||
}
|
||||
else
|
||||
aim.dz = tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, -aim.dz, kMissileFireballTchernobog);
|
||||
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFireballTchernobog);
|
||||
}
|
||||
|
||||
static void sub_72580(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void sub_725A4(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D* pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
aiNewState(actor, &tcherno13AA28);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER *pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x-pSprite->x;
|
||||
int dy = y-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
|
||||
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
|
||||
pDudeExtraE->thinkTime++;
|
||||
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
|
||||
{
|
||||
pXSprite->goalAng += 256;
|
||||
POINT3D* pTarget = &actor->basePoint();
|
||||
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
|
||||
aiNewState(actor, &tcherno13AA28);
|
||||
return;
|
||||
}
|
||||
if (Chance(pDudeInfo->alertChance))
|
||||
{
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER* pPlayer = &gPlayer[p];
|
||||
if (pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x - pSprite->x;
|
||||
int dy = y - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
pDudeExtraE->thinkTime = 0;
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sub_72850(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &tchernobogSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
///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);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &tchernobogSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void sub_72934(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &tcherno13A9B8);
|
||||
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);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &tchernobogSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &tchernobogSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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());
|
||||
if (nDist < 0x1f00 && nDist > 0xd00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tcherno13AA0C);
|
||||
else if (nDist < 0xd00 && nDist > 0xb00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tcherno13A9D4);
|
||||
else if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tcherno13A9F0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &tcherno13A9B8);
|
||||
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);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &tchernobogSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0)
|
||||
{
|
||||
aiNewState(actor, &tchernobogSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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());
|
||||
if (nDist < 0x1f00 && nDist > 0xd00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tcherno13AA0C);
|
||||
else if (nDist < 0xd00 && nDist > 0xb00 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tcherno13A9D4);
|
||||
else if (nDist < 0xb00 && nDist > 0x500 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &tcherno13A9F0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &tcherno13A9B8);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &tcherno13A9B8);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,15 +30,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void zombaThinkSearch(DBloodActor *);
|
||||
static void zombaThinkGoto(DBloodActor *);
|
||||
static void zombaThinkChase(DBloodActor *);
|
||||
static void zombaThinkPonder(DBloodActor *);
|
||||
static void myThinkTarget(DBloodActor *);
|
||||
static void myThinkSearch(DBloodActor *);
|
||||
static void entryEZombie(DBloodActor *);
|
||||
static void entryAIdle(DBloodActor *);
|
||||
static void entryEStand(DBloodActor *);
|
||||
static void zombaThinkSearch(DBloodActor*);
|
||||
static void zombaThinkGoto(DBloodActor*);
|
||||
static void zombaThinkChase(DBloodActor*);
|
||||
static void zombaThinkPonder(DBloodActor*);
|
||||
static void myThinkTarget(DBloodActor*);
|
||||
static void myThinkSearch(DBloodActor*);
|
||||
static void entryEZombie(DBloodActor*);
|
||||
static void entryAIdle(DBloodActor*);
|
||||
static void entryEStand(DBloodActor*);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int tx = pXSprite->targetX-pSprite->x;
|
||||
int ty = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(tx, ty);
|
||||
int height = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2;
|
||||
int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2;
|
||||
int dz = height-height2;
|
||||
int dx = CosScale16(nAngle);
|
||||
int dy = SinScale16(nAngle);
|
||||
sfxPlay3DSound(pSprite, 1101, 1, 0);
|
||||
actFireVector(actor, 0, 0, dx, dy, dz, kVectorAxe);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int tx = pXSprite->targetX - pSprite->x;
|
||||
int ty = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(tx, ty);
|
||||
int height = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2;
|
||||
int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2;
|
||||
int dz = height - height2;
|
||||
int dx = CosScale16(nAngle);
|
||||
int dy = SinScale16(nAngle);
|
||||
sfxPlay3DSound(pSprite, 1101, 1, 0);
|
||||
actFireVector(actor, 0, 0, dx, dy, dz, kVectorAxe);
|
||||
}
|
||||
|
||||
void StandSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
sfxPlay3DSound(actor, 1102, -1, 0);
|
||||
sfxPlay3DSound(actor, 1102, -1, 0);
|
||||
}
|
||||
|
||||
static void zombaThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiLookForTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiLookForTarget(actor);
|
||||
}
|
||||
|
||||
static void zombaThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 921 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &zombieASearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 921 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &zombieASearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void zombaThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpDeathMaskUseless) > 0))
|
||||
{
|
||||
aiNewState(actor, &zombieAGoto);
|
||||
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 (!VanillaMode() && pSprite->type == kDudeZombieAxeBuried)
|
||||
pSprite->type = kDudeZombieAxeNormal;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpDeathMaskUseless) > 0))
|
||||
{
|
||||
aiNewState(actor, &zombieAGoto);
|
||||
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 (!VanillaMode() && pSprite->type == kDudeZombieAxeBuried)
|
||||
pSprite->type = kDudeZombieAxeNormal;
|
||||
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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 (abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &zombieAHack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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 (abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
aiNewState(actor, &zombieAHack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &zombieAGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &zombieAGoto);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void zombaThinkPonder(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpDeathMaskUseless) > 0))
|
||||
{
|
||||
aiNewState(actor, &zombieAGoto);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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 (abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400)
|
||||
{
|
||||
if (abs(nDeltaAngle) < 85)
|
||||
{
|
||||
sfxPlay3DSound(pSprite, 1101, 1, 0);
|
||||
aiNewState(actor, &zombieAHack);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &zombieASearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpDeathMaskUseless) > 0))
|
||||
{
|
||||
aiNewState(actor, &zombieAGoto);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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 (abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x400)
|
||||
{
|
||||
if (abs(nDeltaAngle) < 85)
|
||||
{
|
||||
sfxPlay3DSound(pSprite, 1101, 1, 0);
|
||||
aiNewState(actor, &zombieAHack);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &zombieAChase);
|
||||
aiNewState(actor, &zombieAChase);
|
||||
}
|
||||
|
||||
static void myThinkTarget(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER *pPlayer = &gPlayer[p];
|
||||
int nOwner = (pSprite->owner & 0x1000) ? (pSprite->owner&0xfff) : -1;
|
||||
if (nOwner == pPlayer->nSprite || pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x-pSprite->x;
|
||||
int dy = y-pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z-((pDudeInfo->eyeHeight*pSprite->yrepeat)<<2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
for (int p = connecthead; p >= 0; p = connectpoint2[p])
|
||||
{
|
||||
PLAYER* pPlayer = &gPlayer[p];
|
||||
int nOwner = (pSprite->owner & 0x1000) ? (pSprite->owner & 0xfff) : -1;
|
||||
if (nOwner == pPlayer->nSprite || pPlayer->pXSprite->health == 0 || powerupCheck(pPlayer, kPwUpShadowCloak) > 0)
|
||||
continue;
|
||||
int x = pPlayer->pSprite->x;
|
||||
int y = pPlayer->pSprite->y;
|
||||
int z = pPlayer->pSprite->z;
|
||||
int nSector = pPlayer->pSprite->sectnum;
|
||||
int dx = x - pSprite->x;
|
||||
int dy = y - pSprite->y;
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist)
|
||||
continue;
|
||||
if (!cansee(x, y, z, nSector, pSprite->x, pSprite->y, pSprite->z - ((pDudeInfo->eyeHeight * pSprite->yrepeat) << 2), pSprite->sectnum))
|
||||
continue;
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, pPlayer->actor());
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else if (nDist < pDudeInfo->hearDist)
|
||||
{
|
||||
aiSetTarget(actor, x, y, z);
|
||||
aiActivateDude(actor);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void myThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
myThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
myThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void entryEZombie(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
pSprite->type = kDudeZombieAxeNormal;
|
||||
pSprite->flags |= 1;
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
pSprite->type = kDudeZombieAxeNormal;
|
||||
pSprite->flags |= 1;
|
||||
}
|
||||
|
||||
static void entryAIdle(DBloodActor* actor)
|
||||
{
|
||||
actor->SetTarget(nullptr);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
static void entryEStand(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
sfxPlay3DSound(pSprite, 1100, -1, 0);
|
||||
pSprite->ang = getangle(pXSprite->targetX-pSprite->x, pXSprite->targetY-pSprite->y);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
sfxPlay3DSound(pSprite, 1100, -1, 0);
|
||||
pSprite->ang = getangle(pXSprite->targetX - pSprite->x, pXSprite->targetY - pSprite->y);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
static void zombfThinkSearch(DBloodActor *actor);
|
||||
static void zombfThinkGoto(DBloodActor *actor);
|
||||
static void zombfThinkChase(DBloodActor *actor);
|
||||
static void zombfThinkSearch(DBloodActor* actor);
|
||||
static void zombfThinkGoto(DBloodActor* actor);
|
||||
static void zombfThinkChase(DBloodActor* actor);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (pSprite->type != kDudeZombieButcher)
|
||||
return;
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat);
|
||||
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height2 = (pDudeInfoT->eyeHeight*pTarget->yrepeat);
|
||||
actFireVector(actor, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), height-height2, kVectorCleaver);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (pSprite->type != kDudeZombieButcher)
|
||||
return;
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int height = (pDudeInfo->eyeHeight * pSprite->yrepeat);
|
||||
DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height2 = (pDudeInfoT->eyeHeight * pTarget->yrepeat);
|
||||
actFireVector(actor, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), height - height2, kVectorCleaver);
|
||||
}
|
||||
|
||||
void PukeSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype *pTarget = &actor->GetTarget()->s();
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO *pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height = (pDudeInfo->eyeHeight*pSprite->yrepeat);
|
||||
int height2 = (pDudeInfoT->eyeHeight*pTarget->yrepeat);
|
||||
int tx = pXSprite->targetX-pSprite->x;
|
||||
int ty = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(tx, ty);
|
||||
int dx = CosScale16(nAngle);
|
||||
int dy = SinScale16(nAngle);
|
||||
sfxPlay3DSound(pSprite, 1203, 1, 0);
|
||||
actFireMissile(pSprite, 0, -(height-height2), dx, dy, 0, kMissilePukeGreen);
|
||||
XSPRITE* pXSprite = &actor->x();
|
||||
spritetype* pSprite = &actor->s();
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
spritetype* pTarget = &actor->GetTarget()->s();
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
DUDEINFO* pDudeInfoT = getDudeInfo(pTarget->type);
|
||||
int height = (pDudeInfo->eyeHeight * pSprite->yrepeat);
|
||||
int height2 = (pDudeInfoT->eyeHeight * pTarget->yrepeat);
|
||||
int tx = pXSprite->targetX - pSprite->x;
|
||||
int ty = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(tx, ty);
|
||||
int dx = CosScale16(nAngle);
|
||||
int dy = SinScale16(nAngle);
|
||||
sfxPlay3DSound(pSprite, 1203, 1, 0);
|
||||
actFireMissile(pSprite, 0, -(height - height2), dx, dy, 0, kMissilePukeGreen);
|
||||
}
|
||||
|
||||
void ThrowSeqCallback(int, DBloodActor* actor)
|
||||
{
|
||||
spritetype* pSprite = &actor->s();
|
||||
actFireMissile(pSprite, 0, -getDudeInfo(pSprite->type)->eyeHeight, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileButcherKnife);
|
||||
spritetype* pSprite = &actor->s();
|
||||
actFireMissile(pSprite, 0, -getDudeInfo(pSprite->type)->eyeHeight, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileButcherKnife);
|
||||
}
|
||||
|
||||
static void zombfThinkSearch(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor,pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
aiChooseDirection(actor, pXSprite->goalAng);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void zombfThinkGoto(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX-pSprite->x;
|
||||
int dy = pXSprite->targetY-pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor,nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
aiThinkTarget(actor);
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
int dx = pXSprite->targetX - pSprite->x;
|
||||
int dy = pXSprite->targetY - pSprite->y;
|
||||
int nAngle = getangle(dx, dy);
|
||||
int nDist = approxDist(dx, dy);
|
||||
aiChooseDirection(actor, nAngle);
|
||||
if (nDist < 512 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery)
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
aiThinkTarget(actor);
|
||||
}
|
||||
|
||||
static void zombfThinkChase(DBloodActor* actor)
|
||||
{
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &zombieFGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpDeathMaskUseless) > 0))
|
||||
{
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx,dy)+1024-pSprite->ang)&2047)-1024;
|
||||
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 (abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x1400 && nDist > 0xe00 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
aiNewState(actor, &zombieFThrow);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
aiNewState(actor, &zombieFThrow);
|
||||
else
|
||||
aiNewState(actor, &zombieFDodge);
|
||||
break;
|
||||
default:
|
||||
aiNewState(actor, &zombieFThrow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nDist < 0x1400 && nDist > 0x600 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
aiNewState(actor, &zombieFPuke);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
aiNewState(actor, &zombieFPuke);
|
||||
else
|
||||
aiNewState(actor, &zombieFDodge);
|
||||
break;
|
||||
default:
|
||||
aiNewState(actor, &zombieFPuke);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
aiNewState(actor, &zombieFHack);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
aiNewState(actor, &zombieFHack);
|
||||
else
|
||||
aiNewState(actor, &zombieFDodge);
|
||||
break;
|
||||
default:
|
||||
aiNewState(actor, &zombieFHack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pXSprite = &actor->x();
|
||||
auto pSprite = &actor->s();
|
||||
if (actor->GetTarget() == nullptr)
|
||||
{
|
||||
aiNewState(actor, &zombieFGoto);
|
||||
return;
|
||||
}
|
||||
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||
if (!actor->ValidateTarget(__FUNCTION__)) return;
|
||||
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)
|
||||
{
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
return;
|
||||
}
|
||||
if (IsPlayerSprite(pTarget) && (powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0 || powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpDeathMaskUseless) > 0))
|
||||
{
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
return;
|
||||
}
|
||||
int nDist = approxDist(dx, dy);
|
||||
if (nDist <= pDudeInfo->seeDist)
|
||||
{
|
||||
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pSprite->ang) & 2047) - 1024;
|
||||
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 (abs(nDeltaAngle) <= pDudeInfo->periphery)
|
||||
{
|
||||
aiSetTarget(actor, actor->GetTarget());
|
||||
if (nDist < 0x1400 && nDist > 0xe00 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
aiNewState(actor, &zombieFThrow);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
aiNewState(actor, &zombieFThrow);
|
||||
else
|
||||
aiNewState(actor, &zombieFDodge);
|
||||
break;
|
||||
default:
|
||||
aiNewState(actor, &zombieFThrow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nDist < 0x1400 && nDist > 0x600 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
aiNewState(actor, &zombieFPuke);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
aiNewState(actor, &zombieFPuke);
|
||||
else
|
||||
aiNewState(actor, &zombieFDodge);
|
||||
break;
|
||||
default:
|
||||
aiNewState(actor, &zombieFPuke);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nDist < 0x400 && abs(nDeltaAngle) < 85)
|
||||
{
|
||||
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
|
||||
switch (hit)
|
||||
{
|
||||
case -1:
|
||||
aiNewState(actor, &zombieFHack);
|
||||
break;
|
||||
case 3:
|
||||
if (pSprite->type != gHitInfo.hitactor->s().type)
|
||||
aiNewState(actor, &zombieFHack);
|
||||
else
|
||||
aiNewState(actor, &zombieFDodge);
|
||||
break;
|
||||
default:
|
||||
aiNewState(actor, &zombieFHack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
actor->SetTarget(nullptr);
|
||||
aiNewState(actor, &zombieFSearch);
|
||||
actor->SetTarget(nullptr);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
Loading…
Reference in a new issue