From c485fce958833b12f82946b40eb49a9622d4513b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 16 Sep 2021 21:59:39 +0200 Subject: [PATCH] - reformatted the actor and ai sources. --- source/games/blood/src/actor.cpp | 1090 +++++----- source/games/blood/src/ai.cpp | 3094 +++++++++++++-------------- source/games/blood/src/aibat.cpp | 692 +++--- source/games/blood/src/aibeast.cpp | 962 ++++----- source/games/blood/src/aiboneel.cpp | 682 +++--- source/games/blood/src/aiburn.cpp | 366 ++-- source/games/blood/src/aicaleb.cpp | 662 +++--- source/games/blood/src/aicerber.cpp | 778 +++---- source/games/blood/src/aicult.cpp | 1044 ++++----- source/games/blood/src/aigarg.cpp | 1168 +++++----- source/games/blood/src/aighost.cpp | 982 ++++----- source/games/blood/src/aigilbst.cpp | 654 +++--- source/games/blood/src/aihand.cpp | 150 +- source/games/blood/src/aihound.cpp | 184 +- source/games/blood/src/aiinnoc.cpp | 126 +- source/games/blood/src/aipod.cpp | 340 +-- source/games/blood/src/airat.cpp | 140 +- source/games/blood/src/aispid.cpp | 371 ++-- source/games/blood/src/aitchern.cpp | 556 ++--- source/games/blood/src/aizomba.cpp | 368 ++-- source/games/blood/src/aizombf.cpp | 290 +-- 21 files changed, 7350 insertions(+), 7349 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 07933bf03..a85955e30 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -1659,7 +1659,7 @@ const THINGINFO thingInfo[] = { 0, 256, 256, 128, 64, 0, 0, 128, }, - + // Armed Proxy Dynamite { 5, @@ -2321,7 +2321,7 @@ const int DudeDifficulty[5] = { 512, 384, 256, 208, 160 }; -struct POSTPONE +struct POSTPONE { DBloodActor* sprite; int status; @@ -2396,7 +2396,7 @@ static void actInitThings() if (pSprite->flags & kPhysGravity) pSprite->flags |= kPhysFalling; act->xvel() = act->yvel() = act->zvel() = 0; - switch (pSprite->type) + switch (pSprite->type) { case kThingArmedProxBomb: case kTrapMachinegun: @@ -2994,7 +2994,7 @@ static bool actKillModernDude(DBloodActor* actor, DAMAGE_TYPE damageType) if (pXSprite->dropMsg > 0) // drop items actDropObject(actor, pXSprite->dropMsg); - pSprite->flags &= ~kPhysMove; + pSprite->flags &= ~kPhysMove; actor->xvel() = actor->yvel() = 0; playGenDudeSound(pSprite, kGenDudeSndTransforming); @@ -5035,7 +5035,7 @@ void MoveDude(DBloodActor* actor) if (playerAlive) { pPlayer->fallScream = 1; - sfxPlay3DSound(actor, 719, 0, 0); + sfxPlay3DSound(actor, 719, 0, 0); } } vec3_t const oldpos = pSprite->pos; @@ -5075,14 +5075,14 @@ void MoveDude(DBloodActor* actor) { case kDudeCultistTommy: case kDudeCultistShotgun: - aiNewState(actor, &cultistGoto); + aiNewState(actor, &cultistGoto); break; case kDudeGillBeast: - aiNewState(actor, &gillBeastGoto); + aiNewState(actor, &gillBeastGoto); pSprite->flags |= 6; break; case kDudeBoneEel: - actKillDude(actor, actor, kDamageFall, 1000 << 4); + actKillDude(actor, actor, kDamageFall, 1000 << 4); break; } @@ -5143,7 +5143,7 @@ void MoveDude(DBloodActor* actor) pSprite->type = pSprite->inittype; // restore back to spawned cultist type pXSprite->burnTime = 0; evPost(actor, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(actor, 720, -1, 0); + sfxPlay3DSound(actor, 720, -1, 0); aiNewState(actor, &cultistSwimGoto); break; } @@ -6460,61 +6460,61 @@ DBloodActor* actSpawnDude(DBloodActor* source, short nType, int a3, int a4) if (!spawned) return NULL; spritetype* pSprite2 = &spawned->s(); XSPRITE* pXSprite2 = &spawned->x(); - int angle = pSource->ang; + int angle = pSource->ang; int nDude = nType - kDudeBase; - int x, y, z; - z = a4 + pSource->z; - if (a3 < 0) - { - x = pSource->x; - y = pSource->y; - } - else - { + int x, y, z; + z = a4 + pSource->z; + if (a3 < 0) + { + x = pSource->x; + y = pSource->y; + } + else + { x = pSource->x + mulscale30r(Cos(angle), a3); y = pSource->y + mulscale30r(Sin(angle), a3); - } - pSprite2->type = nType; - pSprite2->ang = angle; - vec3_t pos = { x, y, z }; - setsprite(pSprite2->index, &pos); - pSprite2->cstat |= 0x1101; + } + pSprite2->type = nType; + pSprite2->ang = angle; + vec3_t pos = { x, y, z }; + setsprite(pSprite2->index, &pos); + pSprite2->cstat |= 0x1101; pSprite2->clipdist = getDudeInfo(nDude + kDudeBase)->clipdist; pXSprite2->health = getDudeInfo(nDude + kDudeBase)->startHealth << 4; - pXSprite2->respawn = 1; + pXSprite2->respawn = 1; if (getSequence(getDudeInfo(nDude + kDudeBase)->seqStartID)) seqSpawn(getDudeInfo(nDude + kDudeBase)->seqStartID, spawned, -1); #ifdef NOONE_EXTENSIONS - // add a way to inherit some values of spawner type 18 by dude. - // This way designer can count enemies via switches and do many other interesting things. + // add a way to inherit some values of spawner type 18 by dude. + // This way designer can count enemies via switches and do many other interesting things. if (gModernMap && pSource->flags & kModernTypeFlag1) { // allow inheriting only for selected source types switch (pSource->type) { - case kMarkerDudeSpawn: - //inherit pal? - if (pSprite2->pal <= 0) pSprite2->pal = pSource->pal; + case kMarkerDudeSpawn: + //inherit pal? + if (pSprite2->pal <= 0) pSprite2->pal = pSource->pal; - // inherit spawn sprite trigger settings, so designer can count monsters. - pXSprite2->txID = pXSource->txID; - pXSprite2->command = pXSource->command; - pXSprite2->triggerOn = pXSource->triggerOn; - pXSprite2->triggerOff = pXSource->triggerOff; + // inherit spawn sprite trigger settings, so designer can count monsters. + pXSprite2->txID = pXSource->txID; + pXSprite2->command = pXSource->command; + pXSprite2->triggerOn = pXSource->triggerOn; + pXSprite2->triggerOff = pXSource->triggerOff; - // inherit drop items - pXSprite2->dropMsg = pXSource->dropMsg; + // inherit drop items + pXSprite2->dropMsg = pXSource->dropMsg; - // inherit dude flags - pXSprite2->dudeDeaf = pXSource->dudeDeaf; - pXSprite2->dudeGuard = pXSource->dudeGuard; - pXSprite2->dudeAmbush = pXSource->dudeAmbush; - pXSprite2->dudeFlag4 = pXSource->dudeFlag4; - pXSprite2->unused1 = pXSource->unused1; - break; - } - } + // inherit dude flags + pXSprite2->dudeDeaf = pXSource->dudeDeaf; + pXSprite2->dudeGuard = pXSource->dudeGuard; + pXSprite2->dudeAmbush = pXSource->dudeAmbush; + pXSprite2->dudeFlag4 = pXSource->dudeFlag4; + pXSprite2->unused1 = pXSource->unused1; + break; + } + } #endif aiInitSprite(spawned); @@ -6529,89 +6529,89 @@ DBloodActor* actSpawnDude(DBloodActor* source, short nType, int a3, int a4) DBloodActor* actSpawnThing(int nSector, int x, int y, int z, int nThingType) { - assert(nThingType >= kThingBase && nThingType < kThingMax); + assert(nThingType >= kThingBase && nThingType < kThingMax); auto actor = actSpawnSprite(nSector, x, y, z, 4, 1); spritetype* pSprite = &actor->s(); int nType = nThingType - kThingBase; - pSprite->type = nThingType; + pSprite->type = nThingType; assert(actor->hasX()); XSPRITE* pXThing = &actor->x(); const THINGINFO* pThingInfo = &thingInfo[nType]; pXThing->health = pThingInfo->startHealth << 4; - pSprite->clipdist = pThingInfo->clipdist; - pSprite->flags = pThingInfo->flags; + pSprite->clipdist = pThingInfo->clipdist; + pSprite->flags = pThingInfo->flags; if (pSprite->flags & 2) pSprite->flags |= 4; - pSprite->cstat |= pThingInfo->cstat; - pSprite->picnum = pThingInfo->picnum; - pSprite->shade = pThingInfo->shade; - pSprite->pal = pThingInfo->pal; + pSprite->cstat |= pThingInfo->cstat; + pSprite->picnum = pThingInfo->picnum; + pSprite->shade = pThingInfo->shade; + pSprite->pal = pThingInfo->pal; if (pThingInfo->xrepeat) pSprite->xrepeat = pThingInfo->xrepeat; if (pThingInfo->yrepeat) pSprite->yrepeat = pThingInfo->yrepeat; - show2dsprite.Set(pSprite->index); + show2dsprite.Set(pSprite->index); switch (nThingType) { - case kThingVoodooHead: - pXThing->data1 = 0; - pXThing->data2 = 0; - pXThing->data3 = 0; - pXThing->data4 = 0; - pXThing->state = 1; - pXThing->triggerOnce = 1; - pXThing->isTriggered = 0; - break; + case kThingVoodooHead: + pXThing->data1 = 0; + pXThing->data2 = 0; + pXThing->data3 = 0; + pXThing->data4 = 0; + pXThing->state = 1; + pXThing->triggerOnce = 1; + pXThing->isTriggered = 0; + break; - case kThingDroppedLifeLeech: + case kThingDroppedLifeLeech: #ifdef NOONE_EXTENSIONS - case kModernThingEnemyLifeLeech: + case kModernThingEnemyLifeLeech: #endif - pXThing->data1 = 0; - pXThing->data2 = 0; - pXThing->data3 = 0; - pXThing->data4 = 0; - pXThing->state = 1; - pXThing->triggerOnce = 0; - pXThing->isTriggered = 0; - break; + pXThing->data1 = 0; + pXThing->data2 = 0; + pXThing->data3 = 0; + pXThing->data4 = 0; + pXThing->state = 1; + pXThing->triggerOnce = 0; + pXThing->isTriggered = 0; + break; - case kThingZombieHead: - pXThing->data1 = 8; - pXThing->data2 = 0; - pXThing->data3 = 0; - pXThing->data4 = 318; - pXThing->targetX = PlayClock + 180; - pXThing->locked = 1; - pXThing->state = 1; - pXThing->triggerOnce = 0; - pXThing->isTriggered = 0; - break; + case kThingZombieHead: + pXThing->data1 = 8; + pXThing->data2 = 0; + pXThing->data3 = 0; + pXThing->data4 = 318; + pXThing->targetX = PlayClock + 180; + pXThing->locked = 1; + pXThing->state = 1; + pXThing->triggerOnce = 0; + pXThing->isTriggered = 0; + break; - case kThingBloodBits: - case kThingBloodChunks: - pXThing->data1 = (nThingType == kThingBloodBits) ? 19 : 8; - pXThing->data2 = 0; - pXThing->data3 = 0; - pXThing->data4 = 318; - pXThing->targetX = PlayClock + 180; - pXThing->locked = 1; - pXThing->state = 1; - pXThing->triggerOnce = 0; - pXThing->isTriggered = 0; - break; + case kThingBloodBits: + case kThingBloodChunks: + pXThing->data1 = (nThingType == kThingBloodBits) ? 19 : 8; + pXThing->data2 = 0; + pXThing->data3 = 0; + pXThing->data4 = 318; + pXThing->targetX = PlayClock + 180; + pXThing->locked = 1; + pXThing->state = 1; + pXThing->triggerOnce = 0; + pXThing->isTriggered = 0; + break; - case kThingArmedTNTStick: + case kThingArmedTNTStick: evPost(actor, 0, kCallbackFXDynPuff); sfxPlay3DSound(actor, 450, 0, 0); - break; + break; - case kThingArmedTNTBundle: + case kThingArmedTNTBundle: sfxPlay3DSound(actor, 450, 0, 0); evPost(actor, 0, kCallbackFXDynPuff); - break; + break; - case kThingArmedSpray: + case kThingArmedSpray: evPost(actor, 0, kCallbackFXDynPuff); - break; - } + break; + } return actor; } @@ -6624,21 +6624,21 @@ DBloodActor* actSpawnThing(int nSector, int x, int y, int z, int nThingType) DBloodActor* actFireThing(DBloodActor* actor, int a2, int a3, int a4, int thingType, int a6) { auto pSprite = &actor->s(); - assert(thingType >= kThingBase && thingType < kThingMax); - int x = pSprite->x+MulScale(a2, Cos(pSprite->ang+512), 30); - int y = pSprite->y+MulScale(a2, Sin(pSprite->ang+512), 30); - int z = pSprite->z+a3; - x += MulScale(pSprite->clipdist, Cos(pSprite->ang), 28); - y += MulScale(pSprite->clipdist, Sin(pSprite->ang), 28); + assert(thingType >= kThingBase && thingType < kThingMax); + int x = pSprite->x + MulScale(a2, Cos(pSprite->ang + 512), 30); + int y = pSprite->y + MulScale(a2, Sin(pSprite->ang + 512), 30); + int z = pSprite->z + a3; + x += MulScale(pSprite->clipdist, Cos(pSprite->ang), 28); + y += MulScale(pSprite->clipdist, Sin(pSprite->ang), 28); if (HitScan(pSprite, z, x - pSprite->x, y - pSprite->y, 0, CLIPMASK0, pSprite->clipdist) != -1) - { - x = gHitInfo.hitx-MulScale(pSprite->clipdist<<1, Cos(pSprite->ang), 28); - y = gHitInfo.hity-MulScale(pSprite->clipdist<<1, Sin(pSprite->ang), 28); - } + { + x = gHitInfo.hitx - MulScale(pSprite->clipdist << 1, Cos(pSprite->ang), 28); + y = gHitInfo.hity - MulScale(pSprite->clipdist << 1, Sin(pSprite->ang), 28); + } auto fired = actSpawnThing(pSprite->sectnum, x, y, z, thingType); spritetype* pThing = &fired->s(); - pThing->owner = pSprite->index; - pThing->ang = pSprite->ang; + pThing->owner = pSprite->index; + pThing->ang = pSprite->ang; fired->xvel() = MulScale(a6, Cos(pThing->ang), 30); fired->yvel() = MulScale(a6, Sin(pThing->ang), 30); fired->zvel() = MulScale(a6, a4, 14); @@ -6654,138 +6654,138 @@ DBloodActor* actFireThing(DBloodActor* actor, int a2, int a3, int a4, int thingT // //--------------------------------------------------------------------------- -spritetype* actFireMissile(spritetype *pSprite, int a2, int a3, int a4, int a5, int a6, int nType) +spritetype* actFireMissile(spritetype* pSprite, int a2, int a3, int a4, int a5, int a6, int nType) { - - assert(nType >= kMissileBase && nType < kMissileMax); - char v4 = 0; - int nSprite = pSprite->index; - const MissileType *pMissileInfo = &missileInfo[nType-kMissileBase]; - int x = pSprite->x+MulScale(a2, Cos(pSprite->ang+512), 30); - int y = pSprite->y+MulScale(a2, Sin(pSprite->ang+512), 30); - int z = pSprite->z+a3; - int clipdist = pMissileInfo->clipDist+pSprite->clipdist; - x += MulScale(clipdist, Cos(pSprite->ang), 28); - y += MulScale(clipdist, Sin(pSprite->ang), 28); - int hit = HitScan(pSprite, z, x-pSprite->x, y-pSprite->y, 0, CLIPMASK0, clipdist); - if (hit != -1) - { - if (hit == 3 || hit == 0) - { - v4 = 1; - x = gHitInfo.hitx-MulScale(Cos(pSprite->ang), 16, 30); - y = gHitInfo.hity-MulScale(Sin(pSprite->ang), 16, 30); - } - else - { - x = gHitInfo.hitx-MulScale(pMissileInfo->clipDist<<1, Cos(pSprite->ang), 28); - y = gHitInfo.hity-MulScale(pMissileInfo->clipDist<<1, Sin(pSprite->ang), 28); - } - } + + assert(nType >= kMissileBase && nType < kMissileMax); + char v4 = 0; + int nSprite = pSprite->index; + const MissileType* pMissileInfo = &missileInfo[nType - kMissileBase]; + int x = pSprite->x + MulScale(a2, Cos(pSprite->ang + 512), 30); + int y = pSprite->y + MulScale(a2, Sin(pSprite->ang + 512), 30); + int z = pSprite->z + a3; + int clipdist = pMissileInfo->clipDist + pSprite->clipdist; + x += MulScale(clipdist, Cos(pSprite->ang), 28); + y += MulScale(clipdist, Sin(pSprite->ang), 28); + int hit = HitScan(pSprite, z, x - pSprite->x, y - pSprite->y, 0, CLIPMASK0, clipdist); + if (hit != -1) + { + if (hit == 3 || hit == 0) + { + v4 = 1; + x = gHitInfo.hitx - MulScale(Cos(pSprite->ang), 16, 30); + y = gHitInfo.hity - MulScale(Sin(pSprite->ang), 16, 30); + } + else + { + x = gHitInfo.hitx - MulScale(pMissileInfo->clipDist << 1, Cos(pSprite->ang), 28); + y = gHitInfo.hity - MulScale(pMissileInfo->clipDist << 1, Sin(pSprite->ang), 28); + } + } auto actor = actSpawnSprite(pSprite->sectnum, x, y, z, 5, 1); spritetype* pMissile = &actor->s(); - int nMissile = pMissile->index; - show2dsprite.Set(nMissile); - pMissile->type = nType; - pMissile->shade = pMissileInfo->shade; - pMissile->pal = 0; - pMissile->clipdist = pMissileInfo->clipDist; - pMissile->flags = 1; - pMissile->xrepeat = pMissileInfo->xrepeat; - pMissile->yrepeat = pMissileInfo->yrepeat; - pMissile->picnum = pMissileInfo->picnum; - pMissile->ang = (pSprite->ang+pMissileInfo->angleOfs)&2047; - xvel[nMissile] = MulScale(pMissileInfo->velocity, a4, 14); - yvel[nMissile] = MulScale(pMissileInfo->velocity, a5, 14); - zvel[nMissile] = MulScale(pMissileInfo->velocity, a6, 14); - pMissile->owner = pSprite->index; - pMissile->cstat |= 1; - int nXSprite = pMissile->extra; - assert(nXSprite > 0 && nXSprite < kMaxXSprites); - xsprite[nXSprite].target_i = -1; - evPost(nMissile, 3, 600, kCallbackRemove); - - actBuildMissile(pMissile, nXSprite, nSprite); - - if (v4) - { - actImpactMissile(&bloodActors[pMissile->index], hit); - pMissile = NULL; - } - return pMissile; + int nMissile = pMissile->index; + show2dsprite.Set(nMissile); + pMissile->type = nType; + pMissile->shade = pMissileInfo->shade; + pMissile->pal = 0; + pMissile->clipdist = pMissileInfo->clipDist; + pMissile->flags = 1; + pMissile->xrepeat = pMissileInfo->xrepeat; + pMissile->yrepeat = pMissileInfo->yrepeat; + pMissile->picnum = pMissileInfo->picnum; + pMissile->ang = (pSprite->ang + pMissileInfo->angleOfs) & 2047; + xvel[nMissile] = MulScale(pMissileInfo->velocity, a4, 14); + yvel[nMissile] = MulScale(pMissileInfo->velocity, a5, 14); + zvel[nMissile] = MulScale(pMissileInfo->velocity, a6, 14); + pMissile->owner = pSprite->index; + pMissile->cstat |= 1; + int nXSprite = pMissile->extra; + assert(nXSprite > 0 && nXSprite < kMaxXSprites); + xsprite[nXSprite].target_i = -1; + evPost(nMissile, 3, 600, kCallbackRemove); + + actBuildMissile(pMissile, nXSprite, nSprite); + + if (v4) + { + actImpactMissile(&bloodActors[pMissile->index], hit); + pMissile = NULL; + } + return pMissile; } void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite) { - int nMissile = pMissile->index; - switch (pMissile->type) { - case kMissileLifeLeechRegular: - evPost(nMissile, 3, 0, kCallbackFXFlameLick); - break; - case kMissileTeslaAlt: - evPost(nMissile, 3, 0, kCallbackFXTeslaAlt); - break; - case kMissilePukeGreen: - seqSpawn(29, 3, nXSprite, -1); - break; - case kMissileButcherKnife: - pMissile->cstat |= 16; - break; - case kMissileTeslaRegular: - sfxPlay3DSound(pMissile, 251, 0, 0); - break; - case kMissileEctoSkull: - seqSpawn(2, 3, nXSprite, -1); - sfxPlay3DSound(pMissile, 493, 0, 0); - break; - case kMissileFireballNapalm: - seqSpawn(61, 3, nXSprite, nNapalmClient); - sfxPlay3DSound(pMissile, 441, 0, 0); - break; - case kMissileFireball: - seqSpawn(22, 3, nXSprite, nFireballClient); - sfxPlay3DSound(pMissile, 441, 0, 0); - break; - case kMissileFlameHound: - seqSpawn(27, 3, nXSprite, -1); - xvel[nMissile] += xvel[nSprite] / 2 + Random2(0x11111); - yvel[nMissile] += yvel[nSprite] / 2 + Random2(0x11111); - zvel[nMissile] += zvel[nSprite] / 2 + Random2(0x11111); - break; - case kMissileFireballCerberus: - seqSpawn(61, 3, nXSprite, dword_2192E0); - sfxPlay3DSound(pMissile, 441, 0, 0); - break; - case kMissileFireballTchernobog: - seqSpawn(23, 3, nXSprite, dword_2192D8); - xvel[nMissile] += xvel[nSprite] / 2 + Random2(0x11111); - yvel[nMissile] += yvel[nSprite] / 2 + Random2(0x11111); - zvel[nMissile] += zvel[nSprite] / 2 + Random2(0x11111); - break; - case kMissileFlameSpray: - if (Chance(0x8000)) - seqSpawn(0, 3, nXSprite, -1); - else - seqSpawn(1, 3, nXSprite, -1); - xvel[nMissile] += xvel[nSprite] + Random2(0x11111); - yvel[nMissile] += yvel[nSprite] + Random2(0x11111); - zvel[nMissile] += zvel[nSprite] + Random2(0x11111); - break; - case kMissileFlareAlt: - evPost(nMissile, 3, 30, kCallbackFXFlareBurst); - evPost(nMissile, 3, 0, kCallbackFXFlareSpark); - sfxPlay3DSound(pMissile, 422, 0, 0); - break; - case kMissileFlareRegular: - evPost(nMissile, 3, 0, kCallbackFXFlareSpark); - sfxPlay3DSound(pMissile, 422, 0, 0); - break; - case kMissileLifeLeechAltSmall: - evPost(nMissile, 3, 0, kCallbackFXArcSpark); - break; - case kMissileArcGargoyle: - sfxPlay3DSound(pMissile, 252, 0, 0); - break; - } + int nMissile = pMissile->index; + switch (pMissile->type) { + case kMissileLifeLeechRegular: + evPost(nMissile, 3, 0, kCallbackFXFlameLick); + break; + case kMissileTeslaAlt: + evPost(nMissile, 3, 0, kCallbackFXTeslaAlt); + break; + case kMissilePukeGreen: + seqSpawn(29, 3, nXSprite, -1); + break; + case kMissileButcherKnife: + pMissile->cstat |= 16; + break; + case kMissileTeslaRegular: + sfxPlay3DSound(pMissile, 251, 0, 0); + break; + case kMissileEctoSkull: + seqSpawn(2, 3, nXSprite, -1); + sfxPlay3DSound(pMissile, 493, 0, 0); + break; + case kMissileFireballNapalm: + seqSpawn(61, 3, nXSprite, nNapalmClient); + sfxPlay3DSound(pMissile, 441, 0, 0); + break; + case kMissileFireball: + seqSpawn(22, 3, nXSprite, nFireballClient); + sfxPlay3DSound(pMissile, 441, 0, 0); + break; + case kMissileFlameHound: + seqSpawn(27, 3, nXSprite, -1); + xvel[nMissile] += xvel[nSprite] / 2 + Random2(0x11111); + yvel[nMissile] += yvel[nSprite] / 2 + Random2(0x11111); + zvel[nMissile] += zvel[nSprite] / 2 + Random2(0x11111); + break; + case kMissileFireballCerberus: + seqSpawn(61, 3, nXSprite, dword_2192E0); + sfxPlay3DSound(pMissile, 441, 0, 0); + break; + case kMissileFireballTchernobog: + seqSpawn(23, 3, nXSprite, dword_2192D8); + xvel[nMissile] += xvel[nSprite] / 2 + Random2(0x11111); + yvel[nMissile] += yvel[nSprite] / 2 + Random2(0x11111); + zvel[nMissile] += zvel[nSprite] / 2 + Random2(0x11111); + break; + case kMissileFlameSpray: + if (Chance(0x8000)) + seqSpawn(0, 3, nXSprite, -1); + else + seqSpawn(1, 3, nXSprite, -1); + xvel[nMissile] += xvel[nSprite] + Random2(0x11111); + yvel[nMissile] += yvel[nSprite] + Random2(0x11111); + zvel[nMissile] += zvel[nSprite] + Random2(0x11111); + break; + case kMissileFlareAlt: + evPost(nMissile, 3, 30, kCallbackFXFlareBurst); + evPost(nMissile, 3, 0, kCallbackFXFlareSpark); + sfxPlay3DSound(pMissile, 422, 0, 0); + break; + case kMissileFlareRegular: + evPost(nMissile, 3, 0, kCallbackFXFlareSpark); + sfxPlay3DSound(pMissile, 422, 0, 0); + break; + case kMissileLifeLeechAltSmall: + evPost(nMissile, 3, 0, kCallbackFXArcSpark); + break; + case kMissileArcGargoyle: + sfxPlay3DSound(pMissile, 252, 0, 0); + break; + } } int actGetRespawnTime(DBloodActor* actor) @@ -6798,45 +6798,45 @@ int actGetRespawnTime(DBloodActor* actor) if (actor->IsDudeActor() && !actor->IsPlayerActor()) { if (pXSprite->respawn == 2 || (pXSprite->respawn != 1 && gGameOptions.nMonsterSettings == 2)) - return gGameOptions.nMonsterRespawnTime; - return -1; - } + return gGameOptions.nMonsterRespawnTime; + return -1; + } if (actor->IsWeaponActor()) { - if (pXSprite->respawn == 3 || gGameOptions.nWeaponSettings == 1) return 0; + if (pXSprite->respawn == 3 || gGameOptions.nWeaponSettings == 1) return 0; else if (pXSprite->respawn != 1 && gGameOptions.nWeaponSettings != 0) - return gGameOptions.nWeaponRespawnTime; - return -1; - } + return gGameOptions.nWeaponRespawnTime; + return -1; + } if (actor->IsAmmoActor()) { if (pXSprite->respawn == 2 || (pXSprite->respawn != 1 && gGameOptions.nWeaponSettings != 0)) - return gGameOptions.nWeaponRespawnTime; - return -1; - } + return gGameOptions.nWeaponRespawnTime; + return -1; + } if (actor->IsItemActor()) { - if (pXSprite->respawn == 3 && gGameOptions.nGameType == 1) return 0; + if (pXSprite->respawn == 3 && gGameOptions.nGameType == 1) return 0; else if (pXSprite->respawn == 2 || (pXSprite->respawn != 1 && gGameOptions.nItemSettings != 0)) { switch (pSprite->type) { - case kItemShadowCloak: - case kItemTwoGuns: - case kItemReflectShots: - return gGameOptions.nSpecialRespawnTime; - case kItemDeathMask: + case kItemShadowCloak: + case kItemTwoGuns: + case kItemReflectShots: + return gGameOptions.nSpecialRespawnTime; + case kItemDeathMask: return gGameOptions.nSpecialRespawnTime << 1; - default: - return gGameOptions.nItemRespawnTime; - } - } - return -1; - } - return -1; + default: + return gGameOptions.nItemRespawnTime; + } + } + return -1; + } + return -1; } //--------------------------------------------------------------------------- @@ -6849,36 +6849,36 @@ bool actCheckRespawn(DBloodActor* actor) { spritetype* pSprite = &actor->s(); if (actor->hasX()) - { + { XSPRITE* pXSprite = &actor->x(); int nRespawnTime = actGetRespawnTime(actor); if (nRespawnTime < 0) return 0; - pXSprite->respawnPending = 1; - if (pSprite->type >= kThingBase && pSprite->type < kThingMax) - { - pXSprite->respawnPending = 3; + pXSprite->respawnPending = 1; + if (pSprite->type >= kThingBase && pSprite->type < kThingMax) + { + pXSprite->respawnPending = 3; if (pSprite->type == kThingTNTBarrel) pSprite->cstat |= 32768; - } - if (nRespawnTime > 0) - { + } + if (nRespawnTime > 0) + { if (pXSprite->respawnPending == 1) nRespawnTime = MulScale(nRespawnTime, 0xa000, 16); - pSprite->owner = pSprite->statnum; + pSprite->owner = pSprite->statnum; actPostSprite(actor, kStatRespawn); - pSprite->flags |= kHitagRespawn; + pSprite->flags |= kHitagRespawn; - if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) - { - pSprite->cstat &= ~257; + if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) + { + pSprite->cstat &= ~257; pSprite->x = actor->basePoint().x; pSprite->y = actor->basePoint().y; pSprite->z = actor->basePoint().z; - } + } evPost(actor, nRespawnTime, kCallbackRespawn); - } - return 1; - } - return 0; + } + return 1; + } + return 0; } //--------------------------------------------------------------------------- @@ -6889,20 +6889,20 @@ bool actCheckRespawn(DBloodActor* actor) bool actCanSplatWall(int nWall) { - assert(nWall >= 0 && nWall < kMaxWalls); + assert(nWall >= 0 && nWall < kMaxWalls); walltype* pWall = &wall[nWall]; if (pWall->cstat & 16384) return 0; if (pWall->cstat & 32768) return 0; - int nType = GetWallType(nWall); + int nType = GetWallType(nWall); if (nType >= kWallBase && nType < kWallMax) return 0; - if (pWall->nextsector != -1) - { + if (pWall->nextsector != -1) + { sectortype* pSector = §or[pWall->nextsector]; if (pSector->type >= kSectorBase && pSector->type < kSectorMax) return 0; - } - return 1; + } + return 1; } //--------------------------------------------------------------------------- @@ -6914,258 +6914,258 @@ bool actCanSplatWall(int nWall) void actFireVector(DBloodActor* shooter, int a2, int a3, int a4, int a5, int a6, VECTOR_TYPE vectorType) { auto pShooter = &shooter->s(); - assert(vectorType >= 0 && vectorType < kVectorMax); + assert(vectorType >= 0 && vectorType < kVectorMax); const VECTORDATA* pVectorData = &gVectorData[vectorType]; - int nRange = pVectorData->maxDist; - int hit = VectorScan(pShooter, a2, a3, a4, a5, a6, nRange, 1); - if (hit == 3) - { + int nRange = pVectorData->maxDist; + int hit = VectorScan(pShooter, a2, a3, a4, a5, a6, nRange, 1); + if (hit == 3) + { auto hitactor = gHitInfo.hitactor; assert(hitactor != nullptr); spritetype* pSprite = &hitactor->s(); - if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pShooter, pSprite)) return; + if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pShooter, pSprite)) return; if (IsPlayerSprite(pSprite)) { PLAYER* pPlayer = &gPlayer[pSprite->type - kDudePlayer1]; - if (powerupCheck(pPlayer, kPwUpReflectShots)) - { + if (powerupCheck(pPlayer, kPwUpReflectShots)) + { gHitInfo.hitactor = shooter; - gHitInfo.hitx = pShooter->x; - gHitInfo.hity = pShooter->y; - gHitInfo.hitz = pShooter->z; - } - } - } + gHitInfo.hitx = pShooter->x; + gHitInfo.hity = pShooter->y; + gHitInfo.hitz = pShooter->z; + } + } + } int x = gHitInfo.hitx - MulScale(a4, 16, 14); int y = gHitInfo.hity - MulScale(a5, 16, 14); int z = gHitInfo.hitz - MulScale(a6, 256, 14); - short nSector = gHitInfo.hitsect; - uint8_t nSurf = kSurfNone; + short nSector = gHitInfo.hitsect; + uint8_t nSurf = kSurfNone; if (nRange == 0 || approxDist(gHitInfo.hitx - pShooter->x, gHitInfo.hity - pShooter->y) < nRange) - { - switch (hit) - { - case 1: - { - int nSector = gHitInfo.hitsect; + { + switch (hit) + { + case 1: + { + int nSector = gHitInfo.hitsect; if (sector[nSector].ceilingstat & 1) - nSurf = kSurfNone; - else - nSurf = surfType[sector[nSector].ceilingpicnum]; - break; - } - case 2: - { - int nSector = gHitInfo.hitsect; + nSurf = kSurfNone; + else + nSurf = surfType[sector[nSector].ceilingpicnum]; + break; + } + case 2: + { + int nSector = gHitInfo.hitsect; if (sector[nSector].floorstat & 1) - nSurf = kSurfNone; - else - nSurf = surfType[sector[nSector].floorpicnum]; - break; - } - case 0: - { - int nWall = gHitInfo.hitwall; - assert(nWall >= 0 && nWall < kMaxWalls); - nSurf = surfType[wall[nWall].picnum]; - if (actCanSplatWall(nWall)) - { + nSurf = kSurfNone; + else + nSurf = surfType[sector[nSector].floorpicnum]; + break; + } + case 0: + { + int nWall = gHitInfo.hitwall; + assert(nWall >= 0 && nWall < kMaxWalls); + nSurf = surfType[wall[nWall].picnum]; + if (actCanSplatWall(nWall)) + { int x = gHitInfo.hitx - MulScale(a4, 16, 14); int y = gHitInfo.hity - MulScale(a5, 16, 14); int z = gHitInfo.hitz - MulScale(a6, 256, 14); - int nSurf = surfType[wall[nWall].picnum]; - assert(nSurf < kSurfMax); - if (pVectorData->surfHit[nSurf].fx1 >= 0) - { + int nSurf = surfType[wall[nWall].picnum]; + assert(nSurf < kSurfMax); + if (pVectorData->surfHit[nSurf].fx1 >= 0) + { auto pFX = gFX.fxSpawnActor(pVectorData->surfHit[nSurf].fx1, nSector, x, y, z, 0); - if (pFX) - { + if (pFX) + { pFX->s().ang = (GetWallAngle(nWall) + 512) & 2047; pFX->s().cstat |= 16; - } - } - } - break; - } - case 4: - { - int nWall = gHitInfo.hitwall; - assert(nWall >= 0 && nWall < kMaxWalls); - nSurf = surfType[wall[nWall].overpicnum]; - int nXWall = wall[nWall].extra; - if (nXWall > 0) - { + } + } + } + break; + } + case 4: + { + int nWall = gHitInfo.hitwall; + assert(nWall >= 0 && nWall < kMaxWalls); + nSurf = surfType[wall[nWall].overpicnum]; + int nXWall = wall[nWall].extra; + if (nXWall > 0) + { XWALL* pXWall = &xwall[nXWall]; - if (pXWall->triggerVector) - trTriggerWall(nWall, pXWall, kCmdWallImpact); - } - break; - } - case 3: - { + if (pXWall->triggerVector) + trTriggerWall(nWall, pXWall, kCmdWallImpact); + } + break; + } + case 3: + { auto actor = gHitInfo.hitactor; spritetype* pSprite = &actor->s(); nSurf = surfType[pSprite->picnum]; - x -= MulScale(a4, 112, 14); - y -= MulScale(a5, 112, 14); + x -= MulScale(a4, 112, 14); + y -= MulScale(a5, 112, 14); z -= MulScale(a6, 112 << 4, 14); - int shift = 4; + int shift = 4; if (vectorType == kVectorTine && !actor->IsPlayerActor()) shift = 3; actDamageSprite(shooter, actor, pVectorData->dmgType, pVectorData->dmg << shift); if (actor->hasX() && actor->x().Vector) trTriggerSprite(actor, kCmdSpriteImpact); - if (pSprite->statnum == kStatThing) - { + if (pSprite->statnum == kStatThing) + { int t = thingInfo[pSprite->type - kThingBase].mass; - if (t > 0 && pVectorData->impulse) - { - int t2 = DivScale(pVectorData->impulse, t, 8); + if (t > 0 && pVectorData->impulse) + { + int t2 = DivScale(pVectorData->impulse, t, 8); actor->xvel() += MulScale(a4, t2, 16); actor->yvel() += MulScale(a5, t2, 16); actor->zvel() += MulScale(a6, t2, 16); - } - if (pVectorData->burnTime) - { + } + if (pVectorData->burnTime) + { if (!actor->x().burnTime) evPost(actor, 0, kCallbackFXFlameLick); actBurnSprite(shooter->GetOwner(), actor, pVectorData->burnTime); - } - } - if (pSprite->statnum == kStatDude && actor->hasX()) - { - int t = getDudeInfo(pSprite->type)->mass; + } + } + if (pSprite->statnum == kStatDude && actor->hasX()) + { + int t = getDudeInfo(pSprite->type)->mass; #ifdef NOONE_EXTENSIONS if (actor->IsDudeActor()) { switch (pSprite->type) { - case kDudeModernCustom: - case kDudeModernCustomBurning: - t = getSpriteMassBySize(pSprite); - break; - } - } + case kDudeModernCustom: + case kDudeModernCustomBurning: + t = getSpriteMassBySize(pSprite); + break; + } + } #endif - if (t > 0 && pVectorData->impulse) - { - int t2 = DivScale(pVectorData->impulse, t, 8); + if (t > 0 && pVectorData->impulse) + { + int t2 = DivScale(pVectorData->impulse, t, 8); actor->xvel() += MulScale(a4, t2, 16); actor->yvel() += MulScale(a5, t2, 16); actor->zvel() += MulScale(a6, t2, 16); - } - if (pVectorData->burnTime) - { + } + if (pVectorData->burnTime) + { if (!actor->x().burnTime) evPost(actor, 0, kCallbackFXFlameLick); actBurnSprite(shooter->GetOwner(), actor, pVectorData->burnTime); - } - if (Chance(pVectorData->fxChance)) - { - int t = gVectorData[19].maxDist; - a4 += Random3(4000); - a5 += Random3(4000); - a6 += Random3(4000); - if (HitScan(pSprite, gHitInfo.hitz, a4, a5, a6, CLIPMASK1, t) == 0) - { + } + if (Chance(pVectorData->fxChance)) + { + int t = gVectorData[19].maxDist; + a4 += Random3(4000); + a5 += Random3(4000); + a6 += Random3(4000); + if (HitScan(pSprite, gHitInfo.hitz, a4, a5, a6, CLIPMASK1, t) == 0) + { if (approxDist(gHitInfo.hitx - pSprite->x, gHitInfo.hity - pSprite->y) <= t) - { - int nWall = gHitInfo.hitwall; - int nSector = gHitInfo.hitsect; - if (actCanSplatWall(nWall)) - { - int x = gHitInfo.hitx - MulScale(a4, 16, 14); - int y = gHitInfo.hity - MulScale(a5, 16, 14); + { + int nWall = gHitInfo.hitwall; + int nSector = gHitInfo.hitsect; + if (actCanSplatWall(nWall)) + { + int x = gHitInfo.hitx - MulScale(a4, 16, 14); + int y = gHitInfo.hity - MulScale(a5, 16, 14); int z = gHitInfo.hitz - MulScale(a6, 16 << 4, 14); - int nSurf = surfType[wall[nWall].picnum]; + int nSurf = surfType[wall[nWall].picnum]; const VECTORDATA* pVectorData = &gVectorData[19]; - FX_ID t2 = pVectorData->surfHit[nSurf].fx2; - FX_ID t3 = pVectorData->surfHit[nSurf].fx3; + FX_ID t2 = pVectorData->surfHit[nSurf].fx2; + FX_ID t3 = pVectorData->surfHit[nSurf].fx3; DBloodActor* pFX = nullptr; if (t2 > FX_NONE && (t3 == FX_NONE || Chance(0x4000))) pFX = gFX.fxSpawnActor(t2, nSector, x, y, z, 0); else if (t3 > FX_NONE) pFX = gFX.fxSpawnActor(t3, nSector, x, y, z, 0); - if (pFX) - { + if (pFX) + { pFX->zvel() = 0x2222; pFX->s().ang = (GetWallAngle(nWall) + 512) & 2047; pFX->s().cstat |= 16; - } - } - } - } - } - for (int i = 0; i < pVectorData->bloodSplats; i++) - if (Chance(pVectorData->splatChance)) + } + } + } + } + } + for (int i = 0; i < pVectorData->bloodSplats; i++) + if (Chance(pVectorData->splatChance)) fxSpawnBlood(pSprite, pVectorData->dmg << 4); - } + } #ifdef NOONE_EXTENSIONS - // add impulse for sprites from physics list + // add impulse for sprites from physics list if (gPhysSpritesCount > 0 && pVectorData->impulse) { - - if (actor->hasX()) + + if (actor->hasX()) { - XSPRITE* pXSprite = &actor->x(); - if (pXSprite->physAttr & kPhysDebrisVector) { - - int impulse = DivScale(pVectorData->impulse, ClipLow(gSpriteMass[pSprite->extra].mass, 10), 6); - actor->xvel() += MulScale(a4, impulse, 16); + XSPRITE* pXSprite = &actor->x(); + if (pXSprite->physAttr & kPhysDebrisVector) { + + int impulse = DivScale(pVectorData->impulse, ClipLow(gSpriteMass[pSprite->extra].mass, 10), 6); + actor->xvel() += MulScale(a4, impulse, 16); actor->yvel() += MulScale(a5, impulse, 16); actor->zvel() += MulScale(a6, impulse, 16); - if (pVectorData->burnTime != 0) { - if (!pXSprite->burnTime) evPost(actor, 0, kCallbackFXFlameLick); - actBurnSprite(shooter->GetOwner(), actor, pVectorData->burnTime); - } + if (pVectorData->burnTime != 0) { + if (!pXSprite->burnTime) evPost(actor, 0, kCallbackFXFlameLick); + actBurnSprite(shooter->GetOwner(), actor, pVectorData->burnTime); + } - if (pSprite->type >= kThingBase && pSprite->type < kThingMax) { - pSprite->statnum = kStatThing; // temporary change statnum property - actDamageSprite(shooter, actor, pVectorData->dmgType, pVectorData->dmg << 4); - pSprite->statnum = kStatDecoration; // return statnum property back - } + if (pSprite->type >= kThingBase && pSprite->type < kThingMax) { + pSprite->statnum = kStatThing; // temporary change statnum property + actDamageSprite(shooter, actor, pVectorData->dmgType, pVectorData->dmg << 4); + pSprite->statnum = kStatDecoration; // return statnum property back + } - } + } - } + } - } - #endif - break; - } - } - } - assert(nSurf < kSurfMax); + } +#endif + break; + } + } + } + assert(nSurf < kSurfMax); #ifdef NOONE_EXTENSIONS - - // let the patrol enemies hear surface hit sounds! - - if (pVectorData->surfHit[nSurf].fx2 >= 0) { - - spritetype* pFX2 = gFX.fxSpawn(pVectorData->surfHit[nSurf].fx2, nSector, x, y, z, 0); - if (pFX2 && gModernMap) + + // let the patrol enemies hear surface hit sounds! + + if (pVectorData->surfHit[nSurf].fx2 >= 0) { + + spritetype* pFX2 = gFX.fxSpawn(pVectorData->surfHit[nSurf].fx2, nSector, x, y, z, 0); + if (pFX2 && gModernMap) pFX2->owner = pShooter->index; - } - - if (pVectorData->surfHit[nSurf].fx3 >= 0) { - - spritetype* pFX3 = gFX.fxSpawn(pVectorData->surfHit[nSurf].fx3, nSector, x, y, z, 0); - if (pFX3 && gModernMap) + } + + if (pVectorData->surfHit[nSurf].fx3 >= 0) { + + spritetype* pFX3 = gFX.fxSpawn(pVectorData->surfHit[nSurf].fx3, nSector, x, y, z, 0); + if (pFX3 && gModernMap) pFX3->owner = pShooter->index; - } + } #else - if (pVectorData->surfHit[nSurf].fx2 >= 0) - gFX.fxSpawn(pVectorData->surfHit[nSurf].fx2, nSector, x, y, z, 0); - if (pVectorData->surfHit[nSurf].fx3 >= 0) - gFX.fxSpawn(pVectorData->surfHit[nSurf].fx3, nSector, x, y, z, 0); + if (pVectorData->surfHit[nSurf].fx2 >= 0) + gFX.fxSpawn(pVectorData->surfHit[nSurf].fx2, nSector, x, y, z, 0); + if (pVectorData->surfHit[nSurf].fx3 >= 0) + gFX.fxSpawn(pVectorData->surfHit[nSurf].fx3, nSector, x, y, z, 0); #endif - if (pVectorData->surfHit[nSurf].fxSnd >= 0) - sfxPlay3DSound(x, y, z, pVectorData->surfHit[nSurf].fxSnd, nSector); + if (pVectorData->surfHit[nSurf].fxSnd >= 0) + sfxPlay3DSound(x, y, z, pVectorData->surfHit[nSurf].fxSnd, nSector); } //--------------------------------------------------------------------------- @@ -7178,48 +7178,48 @@ void FireballSeqCallback(int, DBloodActor* actor) { auto pSprite = &actor->s(); auto pFX = gFX.fxSpawnActor(FX_11, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0); - if (pFX) - { + if (pFX) + { pFX->xvel() = actor->xvel(); pFX->yvel() = actor->yvel(); pFX->zvel() = actor->zvel(); - } + } } void NapalmSeqCallback(int, DBloodActor* actor) { auto pSprite = &actor->s(); auto pFX = gFX.fxSpawnActor(FX_12, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0); - if (pFX) - { + if (pFX) + { pFX->xvel() = actor->xvel(); pFX->yvel() = actor->yvel(); pFX->zvel() = actor->zvel(); - } + } } void Fx32Callback(int, DBloodActor* actor) { auto pSprite = &actor->s(); auto pFX = gFX.fxSpawnActor(FX_32, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0); - if (pFX) - { + if (pFX) + { pFX->xvel() = actor->xvel(); pFX->yvel() = actor->yvel(); pFX->zvel() = actor->zvel(); - } + } } void Fx33Callback(int, DBloodActor* actor) { auto pSprite = &actor->s(); auto pFX = gFX.fxSpawnActor(FX_33, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0); - if (pFX) - { + if (pFX) + { pFX->xvel() = actor->xvel(); pFX->yvel() = actor->yvel(); pFX->zvel() = actor->zvel(); - } + } } //--------------------------------------------------------------------------- @@ -7230,50 +7230,50 @@ void Fx33Callback(int, DBloodActor* actor) void TreeToGibCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); + XSPRITE* pXSprite = &actor->x(); spritetype* pSprite = &actor->s(); - pSprite->type = kThingObjectExplode; - pXSprite->state = 1; - pXSprite->data1 = 15; - pXSprite->data2 = 0; - pXSprite->data3 = 0; - pXSprite->health = thingInfo[17].startHealth; - pXSprite->data4 = 312; - pSprite->cstat |= 257; + pSprite->type = kThingObjectExplode; + pXSprite->state = 1; + pXSprite->data1 = 15; + pXSprite->data2 = 0; + pXSprite->data3 = 0; + pXSprite->health = thingInfo[17].startHealth; + pXSprite->data4 = 312; + pSprite->cstat |= 257; } void DudeToGibCallback1(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - pSprite->type = kThingBloodChunks; - pXSprite->data1 = 8; - pXSprite->data2 = 0; - pXSprite->data3 = 0; - pXSprite->health = thingInfo[26].startHealth; - pXSprite->data4 = 319; - pXSprite->triggerOnce = 0; - pXSprite->isTriggered = 0; - pXSprite->locked = 0; - pXSprite->targetX = PlayClock; - pXSprite->state = 1; + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + pSprite->type = kThingBloodChunks; + pXSprite->data1 = 8; + pXSprite->data2 = 0; + pXSprite->data3 = 0; + pXSprite->health = thingInfo[26].startHealth; + pXSprite->data4 = 319; + pXSprite->triggerOnce = 0; + pXSprite->isTriggered = 0; + pXSprite->locked = 0; + pXSprite->targetX = PlayClock; + pXSprite->state = 1; } void DudeToGibCallback2(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - pSprite->type = kThingBloodChunks; - pXSprite->data1 = 3; - pXSprite->data2 = 0; - pXSprite->data3 = 0; - pXSprite->health = thingInfo[26].startHealth; - pXSprite->data4 = 319; - pXSprite->triggerOnce = 0; - pXSprite->isTriggered = 0; - pXSprite->locked = 0; - pXSprite->targetX = PlayClock; - pXSprite->state = 1; + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + pSprite->type = kThingBloodChunks; + pXSprite->data1 = 3; + pXSprite->data2 = 0; + pXSprite->data3 = 0; + pXSprite->health = thingInfo[26].startHealth; + pXSprite->data4 = 319; + pXSprite->triggerOnce = 0; + pXSprite->isTriggered = 0; + pXSprite->locked = 0; + pXSprite->targetX = PlayClock; + pXSprite->state = 1; } //--------------------------------------------------------------------------- @@ -7284,42 +7284,42 @@ void DudeToGibCallback2(int, DBloodActor* actor) void actPostSprite(DBloodActor* actor, int nStatus) { - assert(nStatus >= 0 && nStatus <= kStatFree); + assert(nStatus >= 0 && nStatus <= kStatFree); auto sp = &actor->s(); if (sp->flags & 32) - { + { for (auto& post : gPost) if (post.sprite == actor) { post.status = nStatus; return; - } + } } - else - { + else + { sp->flags |= 32; gPost.Push({ actor, nStatus }); - } + } } void actPostProcess(void) { for (auto& p : gPost) - { + { p.sprite->s().flags &= ~32; int nStatus = p.status; - if (nStatus == kStatFree) - { + if (nStatus == kStatFree) + { if (p.sprite->s().statnum != kStatFree) { evKill(p.sprite); if (p.sprite->hasX()) seqKill(p.sprite); DeleteSprite(p.sprite->s().index); } - } - else + } + else ChangeSpriteStat(p.sprite->s().index, nStatus); - } + } gPost.Clear(); } @@ -7331,32 +7331,32 @@ void actPostProcess(void) void MakeSplash(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - pSprite->flags &= ~2; - int nXSprite = pSprite->extra; - pSprite->z -= 4 << 8; + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + pSprite->flags &= ~2; + int nXSprite = pSprite->extra; + pSprite->z -= 4 << 8; int nSurface = tileGetSurfType(actor->hit().florhit); switch (pSprite->type) { - case kThingDripWater: + case kThingDripWater: switch (nSurface) { - case kSurfWater: + case kSurfWater: seqSpawn(6, actor, -1); sfxPlay3DSound(actor, 356, -1, 0); - break; - default: + break; + default: seqSpawn(7, actor, -1); sfxPlay3DSound(actor, 354, -1, 0); - break; - } - break; - case kThingDripBlood: + break; + } + break; + case kThingDripBlood: seqSpawn(8, actor, -1); sfxPlay3DSound(actor, 354, -1, 0); - break; - } + break; + } } //--------------------------------------------------------------------------- @@ -7367,16 +7367,16 @@ void MakeSplash(DBloodActor* actor) FSerializer& Serialize(FSerializer& arc, const char* keyname, SPRITEHIT& w, SPRITEHIT* def) { - int empty = 0; - if (arc.isReading()) w = {}; - if (arc.BeginObject(keyname)) - { - arc("hit", w.hit, &empty) - ("ceilhit", w.ceilhit, &empty) - ("florhit", w.florhit, &empty) - .EndObject(); - } - return arc; + int empty = 0; + if (arc.isReading()) w = {}; + if (arc.BeginObject(keyname)) + { + arc("hit", w.hit, &empty) + ("ceilhit", w.ceilhit, &empty) + ("florhit", w.florhit, &empty) + .EndObject(); + } + return arc; } void SerializeActor(FSerializer& arc) diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index df7573d63..060c4b718 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -32,10 +32,10 @@ BEGIN_BLD_NS void RecoilDude(DBloodActor* actor); -AISTATE genIdle = {kAiStateGenIdle, 0, -1, 0, NULL, NULL, NULL, NULL }; -AISTATE genRecoil = {kAiStateRecoil, 5, -1, 20, NULL, NULL, NULL, &genIdle }; +AISTATE genIdle = { kAiStateGenIdle, 0, -1, 0, NULL, NULL, NULL, NULL }; +AISTATE genRecoil = { kAiStateRecoil, 5, -1, 20, NULL, NULL, NULL, &genIdle }; -const int dword_138BB0[5] = {0x2000, 0x4000, 0x8000, 0xa000, 0xe000}; +const int dword_138BB0[5] = { 0x2000, 0x4000, 0x8000, 0xa000, 0xe000 }; //--------------------------------------------------------------------------- // @@ -43,16 +43,16 @@ const int dword_138BB0[5] = {0x2000, 0x4000, 0x8000, 0xa000, 0xe000}; // //--------------------------------------------------------------------------- -bool dudeIsPlayingSeq(DBloodActor *actor, int nSeq) +bool dudeIsPlayingSeq(DBloodActor* actor, int nSeq) { - auto pSprite = &actor->s(); - if (pSprite->statnum == kStatDude && pSprite->type >= kDudeBase && pSprite->type < kDudeMax) - { - DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - if (seqGetID(3, pSprite->extra) == pDudeInfo->seqStartID + nSeq && seqGetStatus(3, pSprite->extra) >= 0) - return true; - } - return false; + auto pSprite = &actor->s(); + if (pSprite->statnum == kStatDude && pSprite->type >= kDudeBase && pSprite->type < kDudeMax) + { + DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); + if (seqGetID(3, pSprite->extra) == pDudeInfo->seqStartID + nSeq && seqGetStatus(3, pSprite->extra) >= 0) + return true; + } + return false; } //--------------------------------------------------------------------------- @@ -61,18 +61,18 @@ bool dudeIsPlayingSeq(DBloodActor *actor, int nSeq) // //--------------------------------------------------------------------------- -void aiPlay3DSound(DBloodActor *actor, int a2, AI_SFX_PRIORITY a3, int a4) +void aiPlay3DSound(DBloodActor* actor, int a2, AI_SFX_PRIORITY a3, int a4) { - DUDEEXTRA *pDudeExtra = &actor->dudeExtra; - if (a3 == AI_SFX_PRIORITY_0) - sfxPlay3DSound(actor, a2, a4, 2); - else if (a3 > pDudeExtra->prio || pDudeExtra->time <= PlayClock) - { - sfxKill3DSound(actor, -1, -1); - sfxPlay3DSound(actor, a2, a4, 0); - pDudeExtra->prio = a3; - pDudeExtra->time = PlayClock+120; - } + DUDEEXTRA* pDudeExtra = &actor->dudeExtra; + if (a3 == AI_SFX_PRIORITY_0) + sfxPlay3DSound(actor, a2, a4, 2); + else if (a3 > pDudeExtra->prio || pDudeExtra->time <= PlayClock) + { + sfxKill3DSound(actor, -1, -1); + sfxPlay3DSound(actor, a2, a4, 0); + pDudeExtra->prio = a3; + pDudeExtra->time = PlayClock + 120; + } } //--------------------------------------------------------------------------- @@ -81,24 +81,24 @@ void aiPlay3DSound(DBloodActor *actor, int a2, AI_SFX_PRIORITY a3, int a4) // //--------------------------------------------------------------------------- -void aiNewState(DBloodActor* actor, AISTATE *pAIState) +void aiNewState(DBloodActor* actor, AISTATE* pAIState) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - pXSprite->stateTimer = pAIState->stateTicks; - pXSprite->aiState = pAIState; - int seqStartId = pDudeInfo->seqStartID; + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); + pXSprite->stateTimer = pAIState->stateTicks; + pXSprite->aiState = pAIState; + int seqStartId = pDudeInfo->seqStartID; - if (pAIState->seqId >= 0) - { - seqStartId += pAIState->seqId; - if (getSequence(seqStartId)) - seqSpawn(seqStartId, actor, pAIState->funcId); - } - - if (pAIState->enterFunc) - pAIState->enterFunc(actor); + if (pAIState->seqId >= 0) + { + seqStartId += pAIState->seqId; + if (getSequence(seqStartId)) + seqSpawn(seqStartId, actor, pAIState->funcId); + } + + if (pAIState->enterFunc) + pAIState->enterFunc(actor); } //--------------------------------------------------------------------------- @@ -110,18 +110,18 @@ void aiNewState(DBloodActor* actor, AISTATE *pAIState) static bool isImmune(DBloodActor* actor, int dmgType, int minScale) { - if (dmgType >= kDmgFall && dmgType < kDmgMax && actor->hasX() && actor->x().locked != 1) - { - int type = actor->s().type; - if (type >= kThingBase && type < kThingMax) - return (thingInfo[type - kThingBase].dmgControl[dmgType] <= minScale); - else if (actor->IsDudeActor()) - { - if (actor->IsPlayerActor()) return (gPlayer[type - kDudePlayer1].godMode || gPlayer[type - kDudePlayer1].damageControl[dmgType] <= minScale); - else return (dudeInfo[type - kDudeBase].damageVal[dmgType] <= minScale); - } - } - return true; + if (dmgType >= kDmgFall && dmgType < kDmgMax && actor->hasX() && actor->x().locked != 1) + { + int type = actor->s().type; + if (type >= kThingBase && type < kThingMax) + return (thingInfo[type - kThingBase].dmgControl[dmgType] <= minScale); + else if (actor->IsDudeActor()) + { + if (actor->IsPlayerActor()) return (gPlayer[type - kDudePlayer1].godMode || gPlayer[type - kDudePlayer1].damageControl[dmgType] <= minScale); + else return (dudeInfo[type - kDudeBase].damageVal[dmgType] <= minScale); + } + } + return true; } //--------------------------------------------------------------------------- @@ -130,118 +130,118 @@ static bool isImmune(DBloodActor* actor, int dmgType, int minScale) // //--------------------------------------------------------------------------- -bool CanMove(DBloodActor *actor, DBloodActor* target, int nAngle, int nRange) +bool CanMove(DBloodActor* actor, DBloodActor* target, int nAngle, int nRange) { - auto pSprite = &actor->s(); - int top, bottom; + auto pSprite = &actor->s(); + int top, bottom; GetActorExtents(actor, &top, &bottom); - int x = pSprite->x; - int y = pSprite->y; - int z = pSprite->z; - HitScan(pSprite, z, CosScale16(nAngle), SinScale16(nAngle), 0, CLIPMASK0, nRange); - int nDist = approxDist(x-gHitInfo.hitx, y-gHitInfo.hity); - if (nDist - (pSprite->clipdist << 2) < nRange) - { + int x = pSprite->x; + int y = pSprite->y; + int z = pSprite->z; + HitScan(pSprite, z, CosScale16(nAngle), SinScale16(nAngle), 0, CLIPMASK0, nRange); + int nDist = approxDist(x - gHitInfo.hitx, y - gHitInfo.hity); + if (nDist - (pSprite->clipdist << 2) < nRange) + { if (gHitInfo.hitactor == nullptr || target == nullptr || target != gHitInfo.hitactor) - return false; - return true; - } - x += MulScale(nRange, Cos(nAngle), 30); - y += MulScale(nRange, Sin(nAngle), 30); - int nSector = pSprite->sectnum; - assert(nSector >= 0 && nSector < kMaxSectors); - if (!FindSector(x, y, z, &nSector)) - return false; - int floorZ = getflorzofslope(nSector, x, y); - int nXSector = sector[nSector].extra; - char Underwater = 0; char Water = 0; char Depth = 0; char Crusher = 0; - XSECTOR* pXSector = NULL; - if (nXSector > 0) - { - pXSector = &xsector[nXSector]; - if (pXSector->Underwater) - Underwater = 1; - if (pXSector->Depth) - Depth = 1; - if (sector[nSector].type == kSectorDamage || pXSector->damageType > 0) - Crusher = 1; - } + return false; + return true; + } + x += MulScale(nRange, Cos(nAngle), 30); + y += MulScale(nRange, Sin(nAngle), 30); + int nSector = pSprite->sectnum; + assert(nSector >= 0 && nSector < kMaxSectors); + if (!FindSector(x, y, z, &nSector)) + return false; + int floorZ = getflorzofslope(nSector, x, y); + int nXSector = sector[nSector].extra; + char Underwater = 0; char Water = 0; char Depth = 0; char Crusher = 0; + XSECTOR* pXSector = NULL; + if (nXSector > 0) + { + pXSector = &xsector[nXSector]; + if (pXSector->Underwater) + Underwater = 1; + if (pXSector->Depth) + Depth = 1; + if (sector[nSector].type == kSectorDamage || pXSector->damageType > 0) + Crusher = 1; + } auto Upper = getUpperLink(nSector); auto Lower = getLowerLink(nSector); if (Upper != nullptr) - { + { if (Upper->s().type == kMarkerUpWater || Upper->s().type == kMarkerUpGoo) - Water = Depth = 1; - } + Water = Depth = 1; + } if (Lower != nullptr) - { + { if (Lower->s().type == kMarkerLowWater || Lower->s().type == kMarkerLowGoo) - Depth = 1; - } - switch (pSprite->type) { - case kDudeGargoyleFlesh: - case kDudeGargoyleStone: - case kDudeBat: - if (pSprite->clipdist > nDist) - return 0; - if (Depth) - { - // Ouch... - if (Depth) - return false; - if (Crusher) - return false; - } - break; - case kDudeBoneEel: - if (Water) - return false; - if (!Underwater) - return false; - if (Underwater) - return true; - break; - case kDudeCerberusTwoHead: - case kDudeCerberusOneHead: - // by NoOne: a quick fix for Cerberus spinning in E3M7-like maps, where damage sectors is used. - // It makes ignore danger if enemy immune to N damageType. As result Cerberus start acting like - // in Blood 1.0 so it can move normally to player. It's up to you for adding rest of enemies here as - // i don't think it will broke something in game. - if (!cl_bloodvanillaenemies && !VanillaMode() && Crusher && isImmune(actor, pXSector->damageType, 16)) return true; - [[fallthrough]]; - case kDudeZombieButcher: - case kDudeSpiderBrown: - case kDudeSpiderRed: - case kDudeSpiderBlack: - case kDudeSpiderMother: - case kDudeHellHound: - case kDudeRat: - case kDudeInnocent: - if (Crusher) - return false; - if (Depth || Underwater) - return false; - if (floorZ - bottom > 0x2000) - return false; - break; - #ifdef NOONE_EXTENSIONS - case kDudeModernCustom: - case kDudeModernCustomBurning: - if ((Crusher && !nnExtIsImmune(pSprite, pXSector->damageType)) || ((Water || Underwater) && !canSwim(pSprite))) return false; - return true; - [[fallthrough]]; - #endif - case kDudeZombieAxeNormal: - case kDudePhantasm: - case kDudeGillBeast: - default: - if (Crusher) - return false; - if ((nXSector < 0 || (!xsector[nXSector].Underwater && !xsector[nXSector].Depth)) && floorZ - bottom > 0x2000) - return false; - break; - } - return 1; + Depth = 1; + } + switch (pSprite->type) { + case kDudeGargoyleFlesh: + case kDudeGargoyleStone: + case kDudeBat: + if (pSprite->clipdist > nDist) + return 0; + if (Depth) + { + // Ouch... + if (Depth) + return false; + if (Crusher) + return false; + } + break; + case kDudeBoneEel: + if (Water) + return false; + if (!Underwater) + return false; + if (Underwater) + return true; + break; + case kDudeCerberusTwoHead: + case kDudeCerberusOneHead: + // by NoOne: a quick fix for Cerberus spinning in E3M7-like maps, where damage sectors is used. + // It makes ignore danger if enemy immune to N damageType. As result Cerberus start acting like + // in Blood 1.0 so it can move normally to player. It's up to you for adding rest of enemies here as + // i don't think it will broke something in game. + if (!cl_bloodvanillaenemies && !VanillaMode() && Crusher && isImmune(actor, pXSector->damageType, 16)) return true; + [[fallthrough]]; + case kDudeZombieButcher: + case kDudeSpiderBrown: + case kDudeSpiderRed: + case kDudeSpiderBlack: + case kDudeSpiderMother: + case kDudeHellHound: + case kDudeRat: + case kDudeInnocent: + if (Crusher) + return false; + if (Depth || Underwater) + return false; + if (floorZ - bottom > 0x2000) + return false; + break; +#ifdef NOONE_EXTENSIONS + case kDudeModernCustom: + case kDudeModernCustomBurning: + if ((Crusher && !nnExtIsImmune(pSprite, pXSector->damageType)) || ((Water || Underwater) && !canSwim(pSprite))) return false; + return true; + [[fallthrough]]; +#endif + case kDudeZombieAxeNormal: + case kDudePhantasm: + case kDudeGillBeast: + default: + if (Crusher) + return false; + if ((nXSector < 0 || (!xsector[nXSector].Underwater && !xsector[nXSector].Depth)) && floorZ - bottom > 0x2000) + return false; + break; + } + return 1; } //--------------------------------------------------------------------------- @@ -252,46 +252,46 @@ bool CanMove(DBloodActor *actor, DBloodActor* target, int nAngle, int nRange) void aiChooseDirection(DBloodActor* actor, int a3) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); - assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); - int vc = ((a3+1024-pSprite->ang)&2047)-1024; - int nCos = Cos(pSprite->ang); - int nSin = Sin(pSprite->ang); + assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); + int vc = ((a3 + 1024 - pSprite->ang) & 2047) - 1024; + 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 vsi = ((t1*15)>>12) / 2; - int v8 = 341; - if (vc < 0) - v8 = -341; - if (CanMove(actor, actor->GetTarget(), pSprite->ang+vc, vsi)) - pXSprite->goalAng = pSprite->ang+vc; - else if (CanMove(actor, actor->GetTarget(), pSprite->ang+vc/2, vsi)) - pXSprite->goalAng = pSprite->ang+vc/2; - else if (CanMove(actor, actor->GetTarget(), pSprite->ang-vc/2, vsi)) - pXSprite->goalAng = pSprite->ang-vc/2; - else if (CanMove(actor, actor->GetTarget(), pSprite->ang+v8, vsi)) - pXSprite->goalAng = pSprite->ang+v8; + int t1 = DMulScale(dx, nCos, dy, nSin, 30); + int vsi = ((t1 * 15) >> 12) / 2; + int v8 = 341; + if (vc < 0) + v8 = -341; + if (CanMove(actor, actor->GetTarget(), pSprite->ang + vc, vsi)) + pXSprite->goalAng = pSprite->ang + vc; + else if (CanMove(actor, actor->GetTarget(), pSprite->ang + vc / 2, vsi)) + pXSprite->goalAng = pSprite->ang + vc / 2; + else if (CanMove(actor, actor->GetTarget(), pSprite->ang - vc / 2, vsi)) + pXSprite->goalAng = pSprite->ang - vc / 2; + else if (CanMove(actor, actor->GetTarget(), pSprite->ang + v8, vsi)) + pXSprite->goalAng = pSprite->ang + v8; else if (CanMove(actor, actor->GetTarget(), pSprite->ang, vsi)) - pXSprite->goalAng = pSprite->ang; - else if (CanMove(actor, actor->GetTarget(), pSprite->ang-v8, vsi)) - pXSprite->goalAng = pSprite->ang-v8; - //else if (pSprite->flags&2) - //pXSprite->goalAng = pSprite->ang+341; - else // Weird.. - pXSprite->goalAng = pSprite->ang+341; - if (Chance(0x8000)) - pXSprite->dodgeDir = 1; - else - pXSprite->dodgeDir = -1; - if (!CanMove(actor, actor->GetTarget(), pSprite->ang+pXSprite->dodgeDir*512, 512)) - { - pXSprite->dodgeDir = -pXSprite->dodgeDir; - if (!CanMove(actor, actor->GetTarget(), pSprite->ang+pXSprite->dodgeDir*512, 512)) - pXSprite->dodgeDir = 0; - } + pXSprite->goalAng = pSprite->ang; + else if (CanMove(actor, actor->GetTarget(), pSprite->ang - v8, vsi)) + pXSprite->goalAng = pSprite->ang - v8; + //else if (pSprite->flags&2) + //pXSprite->goalAng = pSprite->ang+341; + else // Weird.. + pXSprite->goalAng = pSprite->ang + 341; + if (Chance(0x8000)) + pXSprite->dodgeDir = 1; + else + pXSprite->dodgeDir = -1; + if (!CanMove(actor, actor->GetTarget(), pSprite->ang + pXSprite->dodgeDir * 512, 512)) + { + pXSprite->dodgeDir = -pXSprite->dodgeDir; + if (!CanMove(actor, actor->GetTarget(), pSprite->ang + pXSprite->dodgeDir * 512, 512)) + pXSprite->dodgeDir = 0; + } } //--------------------------------------------------------------------------- @@ -302,17 +302,17 @@ void aiChooseDirection(DBloodActor* actor, int a3) void aiMoveForward(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 (abs(nAng) > 341) - return; - actor->xvel() += MulScale(pDudeInfo->frontSpeed, Cos(pSprite->ang), 30); - actor->yvel() += MulScale(pDudeInfo->frontSpeed, Sin(pSprite->ang), 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; + if (abs(nAng) > 341) + return; + actor->xvel() += MulScale(pDudeInfo->frontSpeed, Cos(pSprite->ang), 30); + actor->yvel() += MulScale(pDudeInfo->frontSpeed, Sin(pSprite->ang), 30); } //--------------------------------------------------------------------------- @@ -323,13 +323,13 @@ void aiMoveForward(DBloodActor* actor) void aiMoveTurn(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; + 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; } //--------------------------------------------------------------------------- @@ -340,29 +340,29 @@ void aiMoveTurn(DBloodActor* actor) void aiMoveDodge(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) - { - 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) + { + 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->xvel() = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); + } } //--------------------------------------------------------------------------- @@ -373,553 +373,553 @@ void aiMoveDodge(DBloodActor* actor) void aiActivateDude(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); - if (!pXSprite->state) - { - aiChooseDirection(actor, getangle(pXSprite->targetX-pSprite->x, pXSprite->targetY-pSprite->y)); - pXSprite->state = 1; - } - switch (pSprite->type) - { - case kDudePhantasm: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 1; + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); + if (!pXSprite->state) + { + aiChooseDirection(actor, getangle(pXSprite->targetX - pSprite->x, pXSprite->targetY - pSprite->y)); + pXSprite->state = 1; + } + switch (pSprite->type) + { + case kDudePhantasm: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 1; if (actor->GetTarget() == nullptr) - aiNewState(actor, &ghostSearch); - else - { - aiPlay3DSound(actor, 1600, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &ghostChase); - } - break; - } - case kDudeCultistTommy: - case kDudeCultistShotgun: - case kDudeCultistTesla: - case kDudeCultistTNT: - case kDudeCultistBeast: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->active = 1; - if (actor->GetTarget() == nullptr) - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistSearch); - if (Chance(0x8000)) - { - if (pSprite->type == kDudeCultistTommy) aiPlay3DSound(actor, 4008+Random(5), AI_SFX_PRIORITY_1, -1); - else aiPlay3DSound(actor, 1008+Random(5), AI_SFX_PRIORITY_1, -1); - } - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimSearch); - break; - } - } - else - { - if (Chance(0x8000)) - { - if (pSprite->type == kDudeCultistTommy) aiPlay3DSound(actor, 4003+Random(4), AI_SFX_PRIORITY_1, -1); - else aiPlay3DSound(actor, 1003+Random(4), AI_SFX_PRIORITY_1, -1); - } - switch (pXSprite->medium) - { - case kMediumNormal: - if (pSprite->type == kDudeCultistTommy) aiNewState(actor, &fanaticChase); - else aiNewState(actor, &cultistChase); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimChase); - break; - } - } - break; - } -#ifdef NOONE_EXTENSIONS - case kDudeModernCustom: - { - DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->active = 1; - if (actor->GetTarget() == nullptr) + aiNewState(actor, &ghostSearch); + else { - if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchW); - else aiGenDudeNewState(pSprite, &genDudeSearchL); + aiPlay3DSound(actor, 1600, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &ghostChase); + } + break; + } + case kDudeCultistTommy: + case kDudeCultistShotgun: + case kDudeCultistTesla: + case kDudeCultistTNT: + case kDudeCultistBeast: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->active = 1; + if (actor->GetTarget() == nullptr) + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistSearch); + if (Chance(0x8000)) + { + if (pSprite->type == kDudeCultistTommy) aiPlay3DSound(actor, 4008 + Random(5), AI_SFX_PRIORITY_1, -1); + else aiPlay3DSound(actor, 1008 + Random(5), AI_SFX_PRIORITY_1, -1); + } + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimSearch); + break; + } } else { - if (Chance(0x4000)) playGenDudeSound(pSprite, kGenDudeSndTargetSpot); - if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeChaseW); - else aiGenDudeNewState(pSprite, &genDudeChaseL); - } - break; - } - case kDudeModernCustomBurning: + if (Chance(0x8000)) + { + if (pSprite->type == kDudeCultistTommy) aiPlay3DSound(actor, 4003 + Random(4), AI_SFX_PRIORITY_1, -1); + else aiPlay3DSound(actor, 1003 + Random(4), AI_SFX_PRIORITY_1, -1); + } + switch (pXSprite->medium) + { + case kMediumNormal: + if (pSprite->type == kDudeCultistTommy) aiNewState(actor, &fanaticChase); + else aiNewState(actor, &cultistChase); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimChase); + break; + } + } + break; + } +#ifdef NOONE_EXTENSIONS + case kDudeModernCustom: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->active = 1; + if (actor->GetTarget() == nullptr) + { + if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchW); + else aiGenDudeNewState(pSprite, &genDudeSearchL); + } + else + { + if (Chance(0x4000)) playGenDudeSound(pSprite, kGenDudeSndTargetSpot); + if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeChaseW); + else aiGenDudeNewState(pSprite, &genDudeChaseL); + } + break; + } + case kDudeModernCustomBurning: if (actor->GetTarget() == nullptr) aiGenDudeNewState(pSprite, &genDudeBurnSearch); - else aiGenDudeNewState(pSprite, &genDudeBurnChase); - break; + else aiGenDudeNewState(pSprite, &genDudeBurnChase); + break; #endif - case kDudeCultistTommyProne: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->active = 1; - pSprite->type = kDudeCultistTommy; + case kDudeCultistTommyProne: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->active = 1; + pSprite->type = kDudeCultistTommy; if (actor->GetTarget() == nullptr) - { - switch (pXSprite->medium) - { - case 0: - aiNewState(actor, &cultistSearch); - if (Chance(0x8000)) aiPlay3DSound(actor, 4008+Random(5), AI_SFX_PRIORITY_1, -1); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimSearch); - break; - } - } - else - { - if (Chance(0x8000)) - aiPlay3DSound(actor, 4008+Random(5), AI_SFX_PRIORITY_1, -1); - - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistProneChase); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimChase); - break; - } - } - break; - } - case kDudeCultistShotgunProne: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->active = 1; - pSprite->type = kDudeCultistShotgun; - if (actor->GetTarget() == nullptr) - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistSearch); - if (Chance(0x8000)) - aiPlay3DSound(actor, 1008+Random(5), AI_SFX_PRIORITY_1, -1); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimSearch); - break; - } - } - else - { - if (Chance(0x8000)) - aiPlay3DSound(actor, 1003+Random(4), AI_SFX_PRIORITY_1, -1); - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistProneChase); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimChase); - break; - } - } - break; - } - case kDudeBurningCultist: - if (actor->GetTarget() == nullptr) - aiNewState(actor, &cultistBurnSearch); - else - aiNewState(actor, &cultistBurnChase); - break; - case kDudeBat: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 1; - if (!pSprite->flags) - pSprite->flags = 9; - if (actor->GetTarget() == nullptr) - aiNewState(actor, &batSearch); - else - { - if (Chance(0xa000)) - aiPlay3DSound(actor, 2000, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &batChase); - } - break; - } - case kDudeBoneEel: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 1; - if (actor->GetTarget() == nullptr) - aiNewState(actor, &eelSearch); - else - { - if (Chance(0x8000)) - aiPlay3DSound(actor, 1501, AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 1500, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &eelChase); - } - break; - } - case kDudeGillBeast: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - XSECTOR *pXSector = NULL; - if (sector[pSprite->sectnum].extra > 0) - pXSector = &xsector[sector[pSprite->sectnum].extra]; - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 1; - if (actor->GetTarget() == nullptr) - { - if (pXSector && pXSector->Underwater) - aiNewState(actor, &gillBeastSwimSearch); - else - aiNewState(actor, &gillBeastSearch); - } - else - { - if (Chance(0x4000)) - aiPlay3DSound(actor, 1701, AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 1700, AI_SFX_PRIORITY_1, -1); - if (pXSector && pXSector->Underwater) - aiNewState(actor, &gillBeastSwimChase); - else - aiNewState(actor, &gillBeastChase); - } - break; - } - case kDudeZombieAxeNormal: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 1; - if (actor->GetTarget() == nullptr) - aiNewState(actor, &zombieASearch); - else - { - if (Chance(0xa000)) - { - switch (Random(3)) - { - default: - case 0: - case 3: - aiPlay3DSound(actor, 1103, AI_SFX_PRIORITY_1, -1); - break; - case 1: - aiPlay3DSound(actor, 1104, AI_SFX_PRIORITY_1, -1); - break; - case 2: - aiPlay3DSound(actor, 1105, AI_SFX_PRIORITY_1, -1); - break; - } - } - aiNewState(actor, &zombieAChase); - } - break; - } - case kDudeZombieAxeBuried: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 1; - if (pXSprite->aiState == &zombieEIdle) aiNewState(actor, &zombieEUp); - break; - } - case kDudeZombieAxeLaying: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 1; - if (pXSprite->aiState == &zombieSIdle) aiNewState(actor, &zombie13AC2C); - break; - } - case kDudeZombieButcher: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 1; - if (actor->GetTarget() == nullptr) - aiNewState(actor, &zombieFSearch); - else - { - if (Chance(0x4000)) - aiPlay3DSound(actor, 1201, AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 1200, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &zombieFChase); - } - break; - } - case kDudeBurningZombieAxe: - if (actor->GetTarget() == nullptr) - aiNewState(actor, &zombieABurnSearch); - else - aiNewState(actor, &zombieABurnChase); - break; - case kDudeBurningZombieButcher: - if (actor->GetTarget() == nullptr) - aiNewState(actor, &zombieFBurnSearch); - else - aiNewState(actor, &zombieFBurnChase); - break; - case kDudeGargoyleFlesh: { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 1; - if (actor->GetTarget() == nullptr) - aiNewState(actor, &gargoyleFSearch); - else - { - if (Chance(0x4000)) - aiPlay3DSound(actor, 1401, AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &gargoyleFChase); - } - break; - } - case kDudeGargoyleStone: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 1; - if (actor->GetTarget() == nullptr) - aiNewState(actor, &gargoyleFSearch); - else - { - if (Chance(0x4000)) - aiPlay3DSound(actor, 1451, AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 1450, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &gargoyleFChase); - } - break; - } - case kDudeGargoyleStatueFlesh: - case kDudeGargoyleStatueStone: - - #ifdef NOONE_EXTENSIONS - // play gargoyle statue breaking animation if data1 = 1. - if (gModernMap && pXSprite->data1 == 1) - { - if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(actor, &statueFBreakSEQ); - else aiNewState(actor, &statueSBreakSEQ); - } - else - { - if (Chance(0x4000)) aiPlay3DSound(actor, 1401, AI_SFX_PRIORITY_1, -1); - else aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); - - if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(actor, &gargoyleFMorph); - else aiNewState(actor, &gargoyleSMorph); - } - #else - if (Chance(0x4000)) aiPlay3DSound(actor, 1401, AI_SFX_PRIORITY_1, -1); - else aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); + { + switch (pXSprite->medium) + { + case 0: + aiNewState(actor, &cultistSearch); + if (Chance(0x8000)) aiPlay3DSound(actor, 4008 + Random(5), AI_SFX_PRIORITY_1, -1); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimSearch); + break; + } + } + else + { + if (Chance(0x8000)) + aiPlay3DSound(actor, 4008 + Random(5), AI_SFX_PRIORITY_1, -1); - if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(actor, &gargoyleFMorph); - else aiNewState(actor, &gargoyleSMorph); - #endif - break; - case kDudeCerberusTwoHead: + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistProneChase); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimChase); + break; + } + } + break; + } + case kDudeCultistShotgunProne: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->active = 1; + pSprite->type = kDudeCultistShotgun; if (actor->GetTarget() == nullptr) - aiNewState(actor, &cerberusSearch); - else - { - aiPlay3DSound(actor, 2300, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &cerberusChase); - } - break; - case kDudeCerberusOneHead: + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistSearch); + if (Chance(0x8000)) + aiPlay3DSound(actor, 1008 + Random(5), AI_SFX_PRIORITY_1, -1); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimSearch); + break; + } + } + else + { + if (Chance(0x8000)) + aiPlay3DSound(actor, 1003 + Random(4), AI_SFX_PRIORITY_1, -1); + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistProneChase); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimChase); + break; + } + } + break; + } + case kDudeBurningCultist: if (actor->GetTarget() == nullptr) - aiNewState(actor, &cerberus2Search); - else - { - aiPlay3DSound(actor, 2300, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &cerberus2Chase); - } - break; - case kDudeHellHound: + aiNewState(actor, &cultistBurnSearch); + else + aiNewState(actor, &cultistBurnChase); + break; + case kDudeBat: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 1; + if (!pSprite->flags) + pSprite->flags = 9; if (actor->GetTarget() == nullptr) - aiNewState(actor, &houndSearch); - else - { + aiNewState(actor, &batSearch); + else + { + if (Chance(0xa000)) + aiPlay3DSound(actor, 2000, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &batChase); + } + break; + } + case kDudeBoneEel: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 1; + if (actor->GetTarget() == nullptr) + aiNewState(actor, &eelSearch); + else + { + if (Chance(0x8000)) + aiPlay3DSound(actor, 1501, AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 1500, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &eelChase); + } + break; + } + case kDudeGillBeast: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + XSECTOR* pXSector = NULL; + if (sector[pSprite->sectnum].extra > 0) + pXSector = &xsector[sector[pSprite->sectnum].extra]; + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 1; + if (actor->GetTarget() == nullptr) + { + if (pXSector && pXSector->Underwater) + aiNewState(actor, &gillBeastSwimSearch); + else + aiNewState(actor, &gillBeastSearch); + } + else + { + if (Chance(0x4000)) + aiPlay3DSound(actor, 1701, AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 1700, AI_SFX_PRIORITY_1, -1); + if (pXSector && pXSector->Underwater) + aiNewState(actor, &gillBeastSwimChase); + else + aiNewState(actor, &gillBeastChase); + } + break; + } + case kDudeZombieAxeNormal: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 1; + if (actor->GetTarget() == nullptr) + aiNewState(actor, &zombieASearch); + else + { + if (Chance(0xa000)) + { + switch (Random(3)) + { + default: + case 0: + case 3: + aiPlay3DSound(actor, 1103, AI_SFX_PRIORITY_1, -1); + break; + case 1: + aiPlay3DSound(actor, 1104, AI_SFX_PRIORITY_1, -1); + break; + case 2: + aiPlay3DSound(actor, 1105, AI_SFX_PRIORITY_1, -1); + break; + } + } + aiNewState(actor, &zombieAChase); + } + break; + } + case kDudeZombieAxeBuried: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 1; + if (pXSprite->aiState == &zombieEIdle) aiNewState(actor, &zombieEUp); + break; + } + case kDudeZombieAxeLaying: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 1; + if (pXSprite->aiState == &zombieSIdle) aiNewState(actor, &zombie13AC2C); + break; + } + case kDudeZombieButcher: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 1; + if (actor->GetTarget() == nullptr) + aiNewState(actor, &zombieFSearch); + else + { + if (Chance(0x4000)) + aiPlay3DSound(actor, 1201, AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 1200, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &zombieFChase); + } + break; + } + case kDudeBurningZombieAxe: + if (actor->GetTarget() == nullptr) + aiNewState(actor, &zombieABurnSearch); + else + aiNewState(actor, &zombieABurnChase); + break; + case kDudeBurningZombieButcher: + if (actor->GetTarget() == nullptr) + aiNewState(actor, &zombieFBurnSearch); + else + aiNewState(actor, &zombieFBurnChase); + break; + case kDudeGargoyleFlesh: { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 1; + if (actor->GetTarget() == nullptr) + aiNewState(actor, &gargoyleFSearch); + else + { + if (Chance(0x4000)) + aiPlay3DSound(actor, 1401, AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &gargoyleFChase); + } + break; + } + case kDudeGargoyleStone: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 1; + if (actor->GetTarget() == nullptr) + aiNewState(actor, &gargoyleFSearch); + else + { + if (Chance(0x4000)) + aiPlay3DSound(actor, 1451, AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 1450, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &gargoyleFChase); + } + break; + } + case kDudeGargoyleStatueFlesh: + case kDudeGargoyleStatueStone: + +#ifdef NOONE_EXTENSIONS + // play gargoyle statue breaking animation if data1 = 1. + if (gModernMap && pXSprite->data1 == 1) + { + if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(actor, &statueFBreakSEQ); + else aiNewState(actor, &statueSBreakSEQ); + } + else + { + if (Chance(0x4000)) aiPlay3DSound(actor, 1401, AI_SFX_PRIORITY_1, -1); + else aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); + + if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(actor, &gargoyleFMorph); + else aiNewState(actor, &gargoyleSMorph); + } +#else + if (Chance(0x4000)) aiPlay3DSound(actor, 1401, AI_SFX_PRIORITY_1, -1); + else aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); + + if (pSprite->type == kDudeGargoyleStatueFlesh) aiNewState(actor, &gargoyleFMorph); + else aiNewState(actor, &gargoyleSMorph); +#endif + break; + case kDudeCerberusTwoHead: + if (actor->GetTarget() == nullptr) + aiNewState(actor, &cerberusSearch); + else + { + aiPlay3DSound(actor, 2300, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &cerberusChase); + } + break; + case kDudeCerberusOneHead: + if (actor->GetTarget() == nullptr) + aiNewState(actor, &cerberus2Search); + else + { + aiPlay3DSound(actor, 2300, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &cerberus2Chase); + } + break; + case kDudeHellHound: + if (actor->GetTarget() == nullptr) + aiNewState(actor, &houndSearch); + else + { aiPlay3DSound(actor, 1300, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &houndChase); - } - break; - case kDudeHand: + aiNewState(actor, &houndChase); + } + break; + case kDudeHand: if (actor->GetTarget() == nullptr) - aiNewState(actor, &handSearch); - else - { + aiNewState(actor, &handSearch); + else + { aiPlay3DSound(actor, 1900, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &handChase); - } - break; - case kDudeRat: + aiNewState(actor, &handChase); + } + break; + case kDudeRat: if (actor->GetTarget() == nullptr) - aiNewState(actor, &ratSearch); - else - { + aiNewState(actor, &ratSearch); + else + { aiPlay3DSound(actor, 2100, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &ratChase); - } - break; - case kDudeInnocent: + aiNewState(actor, &ratChase); + } + break; + case kDudeInnocent: if (actor->GetTarget() == nullptr) - aiNewState(actor, &innocentSearch); - else - { - if (pXSprite->health > 0) - aiPlay3DSound(actor, 7000+Random(6), AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &innocentChase); - } - break; - case kDudeTchernobog: + aiNewState(actor, &innocentSearch); + else + { + if (pXSprite->health > 0) + aiPlay3DSound(actor, 7000 + Random(6), AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &innocentChase); + } + break; + case kDudeTchernobog: if (actor->GetTarget() == nullptr) - aiNewState(actor, &tchernobogSearch); - else - { - aiPlay3DSound(actor, 2350+Random(7), AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &tchernobogChase); - } - break; - case kDudeSpiderBrown: - case kDudeSpiderRed: - case kDudeSpiderBlack: - pSprite->flags |= 2; - pSprite->cstat &= ~8; + aiNewState(actor, &tchernobogSearch); + else + { + aiPlay3DSound(actor, 2350 + Random(7), AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &tchernobogChase); + } + break; + case kDudeSpiderBrown: + case kDudeSpiderRed: + case kDudeSpiderBlack: + pSprite->flags |= 2; + pSprite->cstat &= ~8; if (actor->GetTarget() == nullptr) - aiNewState(actor, &spidSearch); - else - { - aiPlay3DSound(actor, 1800, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &spidChase); - } - break; - case kDudeSpiderMother: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->active = 1; - pSprite->flags |= 2; - pSprite->cstat &= ~8; + aiNewState(actor, &spidSearch); + else + { + aiPlay3DSound(actor, 1800, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &spidChase); + } + break; + case kDudeSpiderMother: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->active = 1; + pSprite->flags |= 2; + pSprite->cstat &= ~8; if (actor->GetTarget() == nullptr) - aiNewState(actor, &spidSearch); - else - { - aiPlay3DSound(actor, 1853+Random(1), AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &spidChase); - } - break; - } - case kDudeTinyCaleb: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 1; + aiNewState(actor, &spidSearch); + else + { + aiPlay3DSound(actor, 1853 + Random(1), AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &spidChase); + } + break; + } + case kDudeTinyCaleb: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 1; if (actor->GetTarget() == nullptr) - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &tinycalebSearch); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &tinycalebSwimSearch); - break; - } - } - else - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &tinycalebChase); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &tinycalebSwimChase); - break; - } - } - break; - } - case kDudeBeast: - { - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->thinkTime = 1; + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &tinycalebSearch); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &tinycalebSwimSearch); + break; + } + } + else + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &tinycalebChase); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &tinycalebSwimChase); + break; + } + } + break; + } + case kDudeBeast: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->thinkTime = 1; if (actor->GetTarget() == nullptr) - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &beastSearch); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &beastSwimSearch); - break; - } - } - else - { - aiPlay3DSound(actor, 9009+Random(2), AI_SFX_PRIORITY_1, -1); - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &beastChase); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &beastSwimChase); - break; - } - } - break; - } - case kDudePodGreen: - case kDudePodFire: + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &beastSearch); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &beastSwimSearch); + break; + } + } + else + { + aiPlay3DSound(actor, 9009 + Random(2), AI_SFX_PRIORITY_1, -1); + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &beastChase); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &beastSwimChase); + break; + } + } + break; + } + case kDudePodGreen: + case kDudePodFire: if (actor->GetTarget() == nullptr) - aiNewState(actor, &podSearch); - else - { - if (pSprite->type == kDudePodFire) - aiPlay3DSound(actor, 2453, AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 2473, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &podChase); - } - break; - case kDudeTentacleGreen: - case kDudeTentacleFire: + aiNewState(actor, &podSearch); + else + { + if (pSprite->type == kDudePodFire) + aiPlay3DSound(actor, 2453, AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 2473, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &podChase); + } + break; + case kDudeTentacleGreen: + case kDudeTentacleFire: if (actor->GetTarget() == nullptr) - aiNewState(actor, &tentacleSearch); - else - { - aiPlay3DSound(actor, 2503, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &tentacleChase); - } - break; - } + aiNewState(actor, &tentacleSearch); + else + { + aiPlay3DSound(actor, 2503, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &tentacleChase); + } + break; + } } //--------------------------------------------------------------------------- @@ -928,13 +928,13 @@ void aiActivateDude(DBloodActor* actor) // //--------------------------------------------------------------------------- -void aiSetTarget(DBloodActor*actor, int x, int y, int z) +void aiSetTarget(DBloodActor* actor, int x, int y, int z) { auto pXSprite = &actor->x(); actor->SetTarget(nullptr); - pXSprite->targetX = x; - pXSprite->targetY = y; - pXSprite->targetZ = z; + pXSprite->targetX = x; + pXSprite->targetY = y; + pXSprite->targetZ = z; } void aiSetTarget(DBloodActor* actor, DBloodActor* target) @@ -946,17 +946,17 @@ void aiSetTarget(DBloodActor* actor, DBloodActor* target) } auto pXSprite = &actor->x(); spritetype* pTarget = &target->s(); - if (pTarget->type >= kDudeBase && pTarget->type < kDudeMax) - { + if (pTarget->type >= kDudeBase && pTarget->type < kDudeMax) + { if (actor->GetOwner() != target) - { + { actor->SetTarget(target); DUDEINFO* pDudeInfo = getDudeInfo(pTarget->type); - pXSprite->targetX = pTarget->x; - pXSprite->targetY = pTarget->y; + pXSprite->targetX = pTarget->x; + pXSprite->targetY = pTarget->y; pXSprite->targetZ = pTarget->z - ((pDudeInfo->eyeHeight * pTarget->yrepeat) << 2); - } - } + } + } } //--------------------------------------------------------------------------- @@ -967,290 +967,290 @@ void aiSetTarget(DBloodActor* actor, DBloodActor* target) int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType, int nDamage) { - auto pSprite = &actor->s(); - XSPRITE* pXSprite = &actor->x(); + auto pSprite = &actor->s(); + XSPRITE* pXSprite = &actor->x(); - if (!pXSprite->health) - return 0; - pXSprite->health = ClipLow(pXSprite->health - nDamage, 0); + if (!pXSprite->health) + return 0; + pXSprite->health = ClipLow(pXSprite->health - nDamage, 0); actor->cumulDamage += nDamage; - DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); + DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); - if (source) - { - spritetype *pSource = &source->s(); - int nSource = pSource->index; - if (pSprite == pSource) return 0; - else if (actor->GetTarget() == nullptr) // if no target, give the dude a target - { - aiSetTarget(actor, source); + if (source) + { + spritetype* pSource = &source->s(); + int nSource = pSource->index; + if (pSprite == pSource) return 0; + else if (actor->GetTarget() == nullptr) // if no target, give the dude a target + { + aiSetTarget(actor, source); aiActivateDude(actor); - } - else if (source != actor->GetTarget()) // if found a new target, retarget - { - int nThresh = nDamage; - if (pSprite->type == pSource->type) - nThresh *= pDudeInfo->changeTargetKin; - else - nThresh *= pDudeInfo->changeTarget; - if (Chance(nThresh)) - { - aiSetTarget(actor, source); - aiActivateDude(actor); - } - } - - #ifdef NOONE_EXTENSIONS - if (gModernMap) { - - // for enemies in patrol mode - if (aiInPatrolState(pXSprite->aiState)) + } + else if (source != actor->GetTarget()) // if found a new target, retarget + { + int nThresh = nDamage; + if (pSprite->type == pSource->type) + nThresh *= pDudeInfo->changeTargetKin; + else + nThresh *= pDudeInfo->changeTarget; + if (Chance(nThresh)) { - aiPatrolStop(pSprite, pSource->index, pXSprite->dudeAmbush); + aiSetTarget(actor, source); + aiActivateDude(actor); + } + } - PLAYER* pPlayer = getPlayerById(pSource->type); - if (!pPlayer) return nDamage; - if (powerupCheck(pPlayer, kPwUpShadowCloak)) pPlayer->pwUpTime[kPwUpShadowCloak] = 0; - if (readyForCrit(pSource, pSprite)) +#ifdef NOONE_EXTENSIONS + if (gModernMap) { + + // for enemies in patrol mode + if (aiInPatrolState(pXSprite->aiState)) + { + aiPatrolStop(pSprite, pSource->index, pXSprite->dudeAmbush); + + PLAYER* pPlayer = getPlayerById(pSource->type); + if (!pPlayer) return nDamage; + if (powerupCheck(pPlayer, kPwUpShadowCloak)) pPlayer->pwUpTime[kPwUpShadowCloak] = 0; + if (readyForCrit(pSource, pSprite)) { nDamage += aiDamageSprite(actor, source, nDmgType, nDamage * (10 - gGameOptions.nDifficulty)); - if (pXSprite->health > 0) + if (pXSprite->health > 0) { - int fullHp = (pXSprite->sysData2 > 0) ? ClipRange(pXSprite->sysData2 << 4, 1, 65535) : getDudeInfo(pSprite->type)->startHealth << 4; - if (((100 * pXSprite->health) / fullHp) <= 75) + int fullHp = (pXSprite->sysData2 > 0) ? ClipRange(pXSprite->sysData2 << 4, 1, 65535) : getDudeInfo(pSprite->type)->startHealth << 4; + if (((100 * pXSprite->health) / fullHp) <= 75) { actor->cumulDamage += nDamage << 4; // to be sure any enemy will play the recoil animation - RecoilDude(&bloodActors[pXSprite->reference]); - } - } + RecoilDude(&bloodActors[pXSprite->reference]); + } + } - DPrintf(DMSG_SPAMMY, "Player #%d does the critical damage to patrol dude #%d!", pPlayer->nPlayer + 1, pSprite->index); - } + DPrintf(DMSG_SPAMMY, "Player #%d does the critical damage to patrol dude #%d!", pPlayer->nPlayer + 1, pSprite->index); + } - return nDamage; - } + return nDamage; + } - if (pSprite->type == kDudeModernCustomBurning) + if (pSprite->type == kDudeModernCustomBurning) { - if (Chance(0x2000) && actor->dudeExtra.time < PlayClock) { - playGenDudeSound(pSprite, kGenDudeSndBurning); - actor->dudeExtra.time = PlayClock + 360; - } + if (Chance(0x2000) && actor->dudeExtra.time < PlayClock) { + playGenDudeSound(pSprite, kGenDudeSndBurning); + actor->dudeExtra.time = PlayClock + 360; + } - if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400; - if (spriteIsUnderwater(pSprite, false)) + if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400; + if (spriteIsUnderwater(pSprite, false)) { - pSprite->type = kDudeModernCustom; - pXSprite->burnTime = 0; - pXSprite->health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before. - aiGenDudeNewState(pSprite, &genDudeGotoW); - } - - return nDamage; + pSprite->type = kDudeModernCustom; + pXSprite->burnTime = 0; + pXSprite->health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before. + aiGenDudeNewState(pSprite, &genDudeGotoW); + } - } + return nDamage; - if (pSprite->type == kDudeModernCustom) + } + + if (pSprite->type == kDudeModernCustom) { - GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); - if (nDmgType == kDamageBurn) + GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); + if (nDmgType == kDamageBurn) { - if (pXSprite->health > (uint32_t)pDudeInfo->fleeHealth) return nDamage; - else if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == nullptr) + if (pXSprite->health > (uint32_t)pDudeInfo->fleeHealth) return nDamage; + else if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == nullptr) { - removeDudeStuff(pSprite); + removeDudeStuff(pSprite); - if (pExtra->weaponType == kGenDudeWeaponKamikaze) - doExplosion(pSprite, pXSprite->data1 - kTrapExploder); + if (pExtra->weaponType == kGenDudeWeaponKamikaze) + doExplosion(pSprite, pXSprite->data1 - kTrapExploder); - if (spriteIsUnderwater(pSprite)) + if (spriteIsUnderwater(pSprite)) { - pXSprite->health = 0; - return nDamage; - } + pXSprite->health = 0; + return nDamage; + } - if (pXSprite->burnTime <= 0) - pXSprite->burnTime = 1200; + if (pXSprite->burnTime <= 0) + pXSprite->burnTime = 1200; - if (pExtra->canBurn && pExtra->availDeaths[kDamageBurn] > 0) { + if (pExtra->canBurn && pExtra->availDeaths[kDamageBurn] > 0) { aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1); - playGenDudeSound(pSprite, kGenDudeSndBurning); - pSprite->type = kDudeModernCustomBurning; + playGenDudeSound(pSprite, kGenDudeSndBurning); + pSprite->type = kDudeModernCustomBurning; - if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation - pSprite->pal = 0; + if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation + pSprite->pal = 0; - aiGenDudeNewState(pSprite, &genDudeBurnGoto); - actHealDude(actor, dudeInfo[55].startHealth, dudeInfo[55].startHealth); - actor->dudeExtra.time = PlayClock + 360; + aiGenDudeNewState(pSprite, &genDudeBurnGoto); + actHealDude(actor, dudeInfo[55].startHealth, dudeInfo[55].startHealth); + actor->dudeExtra.time = PlayClock + 360; evKill(actor, kCallbackFXFlameLick); - } + } } - else + else { - actKillDude(actor, actor, kDamageFall, 65535); - } - } - else if (canWalk(pSprite) && !inDodge(pXSprite->aiState) && !inRecoil(pXSprite->aiState)) + actKillDude(actor, actor, kDamageFall, 65535); + } + } + else if (canWalk(pSprite) && !inDodge(pXSprite->aiState) && !inRecoil(pXSprite->aiState)) { - if (!dudeIsMelee(pXSprite)) + if (!dudeIsMelee(pXSprite)) { - if (inIdle(pXSprite->aiState) || Chance(getDodgeChance(pSprite))) + if (inIdle(pXSprite->aiState) || Chance(getDodgeChance(pSprite))) { - if (!spriteIsUnderwater(pSprite)) + if (!spriteIsUnderwater(pSprite)) { if (!canDuck(pSprite) || !dudeIsPlayingSeq(actor, 14)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL); - else aiGenDudeNewState(pSprite, &genDudeDodgeShortD); + else aiGenDudeNewState(pSprite, &genDudeDodgeShortD); - if (Chance(0x0200)) - playGenDudeSound(pSprite, kGenDudeSndGotHit); + if (Chance(0x0200)) + playGenDudeSound(pSprite, kGenDudeSndGotHit); - } - else if (dudeIsPlayingSeq(actor, 13)) + } + else if (dudeIsPlayingSeq(actor, 13)) { - aiGenDudeNewState(pSprite, &genDudeDodgeShortW); - } - } + aiGenDudeNewState(pSprite, &genDudeDodgeShortW); + } + } } - else if (Chance(0x0200)) + else if (Chance(0x0200)) { - playGenDudeSound(pSprite, kGenDudeSndGotHit); - } - } - return nDamage; - } - } - #endif + playGenDudeSound(pSprite, kGenDudeSndGotHit); + } + } + return nDamage; + } + } +#endif - if (nDmgType == kDamageTesla) - { - DUDEEXTRA *pDudeExtra = &actor->dudeExtra; - pDudeExtra->teslaHit = 1; - } - else if (!VanillaMode()) // reset tesla hit state if received different type of damage - { - DUDEEXTRA *pDudeExtra = &actor->dudeExtra; - pDudeExtra->teslaHit = 0; - } - const bool fixRandomCultist = !cl_bloodvanillaenemies && (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode(); // fix burning cultists randomly switching types underwater - switch (pSprite->type) - { - case kDudeCultistTommy: - case kDudeCultistShotgun: - case kDudeCultistTesla: - case kDudeCultistTNT: - if (nDmgType != kDamageBurn) - { + if (nDmgType == kDamageTesla) + { + DUDEEXTRA* pDudeExtra = &actor->dudeExtra; + pDudeExtra->teslaHit = 1; + } + else if (!VanillaMode()) // reset tesla hit state if received different type of damage + { + DUDEEXTRA* pDudeExtra = &actor->dudeExtra; + pDudeExtra->teslaHit = 0; + } + const bool fixRandomCultist = !cl_bloodvanillaenemies && (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode(); // fix burning cultists randomly switching types underwater + switch (pSprite->type) + { + case kDudeCultistTommy: + case kDudeCultistShotgun: + case kDudeCultistTesla: + case kDudeCultistTNT: + if (nDmgType != kDamageBurn) + { if (!dudeIsPlayingSeq(actor, 14) && !pXSprite->medium) - aiNewState(actor, &cultistDodge); + aiNewState(actor, &cultistDodge); else if (dudeIsPlayingSeq(actor, 14) && !pXSprite->medium) - aiNewState(actor, &cultistProneDodge); + aiNewState(actor, &cultistProneDodge); else if (dudeIsPlayingSeq(actor, 13) && (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo)) - aiNewState(actor, &cultistSwimDodge); - } - else if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) - { - pSprite->type = kDudeBurningCultist; - aiNewState(actor, &cultistBurnGoto); + aiNewState(actor, &cultistSwimDodge); + } + else if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) + { + pSprite->type = kDudeBurningCultist; + aiNewState(actor, &cultistBurnGoto); aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1); - aiPlay3DSound(actor, 1031+Random(2), AI_SFX_PRIORITY_2, -1); - actor->dudeExtra.time = PlayClock+360; - actHealDude(actor, dudeInfo[40].startHealth, dudeInfo[40].startHealth); + aiPlay3DSound(actor, 1031 + Random(2), AI_SFX_PRIORITY_2, -1); + actor->dudeExtra.time = PlayClock + 360; + actHealDude(actor, dudeInfo[40].startHealth, dudeInfo[40].startHealth); evKill(actor, kCallbackFXFlameLick); - } - break; - case kDudeInnocent: - if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) - { - pSprite->type = kDudeBurningInnocent; - aiNewState(actor, &cultistBurnGoto); + } + break; + case kDudeInnocent: + if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) + { + pSprite->type = kDudeBurningInnocent; + aiNewState(actor, &cultistBurnGoto); aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1); - actor->dudeExtra.time = PlayClock+360; - actHealDude(actor, dudeInfo[39].startHealth, dudeInfo[39].startHealth); + actor->dudeExtra.time = PlayClock + 360; + actHealDude(actor, dudeInfo[39].startHealth, dudeInfo[39].startHealth); evKill(actor, kCallbackFXFlameLick); - } - break; - case kDudeBurningCultist: - if (Chance(0x4000) && actor->dudeExtra.time < PlayClock) - { - aiPlay3DSound(actor, 1031+Random(2), AI_SFX_PRIORITY_2, -1); - actor->dudeExtra.time = PlayClock+360; - } - if (Chance(0x600) && (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo)) - { - pSprite->type = kDudeCultistTommy; - if (fixRandomCultist) // fix burning cultists randomly switching types underwater - pSprite->type = pSprite->inittype; // restore back to spawned cultist type - pXSprite->burnTime = 0; - aiNewState(actor, &cultistSwimGoto); - } - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - { - pSprite->type = kDudeCultistShotgun; - if (fixRandomCultist) // fix burning cultists randomly switching types underwater - pSprite->type = pSprite->inittype; // restore back to spawned cultist type - pXSprite->burnTime = 0; - aiNewState(actor, &cultistSwimGoto); - } - break; - case kDudeGargoyleFlesh: - aiNewState(actor, &gargoyleFChase); - break; - case kDudeZombieButcher: - if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth) { + } + break; + case kDudeBurningCultist: + if (Chance(0x4000) && actor->dudeExtra.time < PlayClock) + { + aiPlay3DSound(actor, 1031 + Random(2), AI_SFX_PRIORITY_2, -1); + actor->dudeExtra.time = PlayClock + 360; + } + if (Chance(0x600) && (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo)) + { + pSprite->type = kDudeCultistTommy; + if (fixRandomCultist) // fix burning cultists randomly switching types underwater + pSprite->type = pSprite->inittype; // restore back to spawned cultist type + pXSprite->burnTime = 0; + aiNewState(actor, &cultistSwimGoto); + } + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + { + pSprite->type = kDudeCultistShotgun; + if (fixRandomCultist) // fix burning cultists randomly switching types underwater + pSprite->type = pSprite->inittype; // restore back to spawned cultist type + pXSprite->burnTime = 0; + aiNewState(actor, &cultistSwimGoto); + } + break; + case kDudeGargoyleFlesh: + aiNewState(actor, &gargoyleFChase); + break; + case kDudeZombieButcher: + if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth) { aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1); aiPlay3DSound(actor, 1202, AI_SFX_PRIORITY_2, -1); - pSprite->type = kDudeBurningZombieButcher; - aiNewState(actor, &zombieFBurnGoto); - actHealDude(actor, dudeInfo[42].startHealth, dudeInfo[42].startHealth); + pSprite->type = kDudeBurningZombieButcher; + aiNewState(actor, &zombieFBurnGoto); + actHealDude(actor, dudeInfo[42].startHealth, dudeInfo[42].startHealth); evKill(actor, kCallbackFXFlameLick); - } - break; - case kDudeTinyCaleb: - if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) - { - if (!cl_bloodvanillaenemies && !VanillaMode()) // fix burning sprite for tiny caleb - { - pSprite->type = kDudeBurningTinyCaleb; - aiNewState(actor, &tinycalebBurnGoto); - } - else - { - pSprite->type = kDudeBurningInnocent; - aiNewState(actor, &cultistBurnGoto); - } - aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1); - actor->dudeExtra.time = PlayClock+360; - actHealDude(actor, dudeInfo[39].startHealth, dudeInfo[39].startHealth); + } + break; + case kDudeTinyCaleb: + if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) + { + if (!cl_bloodvanillaenemies && !VanillaMode()) // fix burning sprite for tiny caleb + { + pSprite->type = kDudeBurningTinyCaleb; + aiNewState(actor, &tinycalebBurnGoto); + } + else + { + pSprite->type = kDudeBurningInnocent; + aiNewState(actor, &cultistBurnGoto); + } + aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1); + actor->dudeExtra.time = PlayClock + 360; + actHealDude(actor, dudeInfo[39].startHealth, dudeInfo[39].startHealth); evKill(actor, kCallbackFXFlameLick); - } - break; - case kDudeCultistBeast: - if (pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth) - { - pSprite->type = kDudeBeast; + } + break; + case kDudeCultistBeast: + if (pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth) + { + pSprite->type = kDudeBeast; aiPlay3DSound(actor, 9008, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &beastMorphFromCultist); - actHealDude(actor, dudeInfo[51].startHealth, dudeInfo[51].startHealth); - } - break; - case kDudeZombieAxeNormal: - case kDudeZombieAxeBuried: - if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth) - { + aiNewState(actor, &beastMorphFromCultist); + actHealDude(actor, dudeInfo[51].startHealth, dudeInfo[51].startHealth); + } + break; + case kDudeZombieAxeNormal: + case kDudeZombieAxeBuried: + if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth) + { aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1); aiPlay3DSound(actor, 1106, AI_SFX_PRIORITY_2, -1); - pSprite->type = kDudeBurningZombieAxe; - aiNewState(actor, &zombieABurnGoto); - actHealDude(actor, dudeInfo[41].startHealth, dudeInfo[41].startHealth); + pSprite->type = kDudeBurningZombieAxe; + aiNewState(actor, &zombieABurnGoto); + actHealDude(actor, dudeInfo[41].startHealth, dudeInfo[41].startHealth); evKill(actor, kCallbackFXFlameLick); - } - break; - } - } - return nDamage; + } + break; + } + } + return nDamage; } //--------------------------------------------------------------------------- @@ -1261,9 +1261,9 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType void RecoilDude(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - char v4 = Chance(0x8000); + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + char v4 = Chance(0x8000); DUDEEXTRA* pDudeExtra = &actor->dudeExtra; if (pSprite->statnum == kStatDude && (pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { @@ -1273,248 +1273,248 @@ void RecoilDude(DBloodActor* actor) #ifdef NOONE_EXTENSIONS case kDudeModernCustom: { - GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); int rChance = getRecoilChance(pSprite); - if (pExtra->canElectrocute && pDudeExtra->teslaHit && !spriteIsUnderwater(pSprite, false)) + GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); int rChance = getRecoilChance(pSprite); + if (pExtra->canElectrocute && pDudeExtra->teslaHit && !spriteIsUnderwater(pSprite, false)) { - - if (Chance(rChance << 3) || (dudeIsMelee(pXSprite) && Chance(rChance << 4))) aiGenDudeNewState(pSprite, &genDudeRecoilTesla); - else if (pExtra->canRecoil && Chance(rChance)) aiGenDudeNewState(pSprite, &genDudeRecoilL); + + if (Chance(rChance << 3) || (dudeIsMelee(pXSprite) && Chance(rChance << 4))) aiGenDudeNewState(pSprite, &genDudeRecoilTesla); + else if (pExtra->canRecoil && Chance(rChance)) aiGenDudeNewState(pSprite, &genDudeRecoilL); else if (canWalk(pSprite)) { - if (Chance(rChance >> 2)) aiGenDudeNewState(pSprite, &genDudeDodgeL); - else if (Chance(rChance >> 1)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL); + if (Chance(rChance >> 2)) aiGenDudeNewState(pSprite, &genDudeDodgeL); + else if (Chance(rChance >> 1)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL); - } + } } else if (pExtra->canRecoil && Chance(rChance)) { - if (inDuck(pXSprite->aiState) && Chance(rChance >> 2)) aiGenDudeNewState(pSprite, &genDudeRecoilD); - else if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeRecoilW); - else aiGenDudeNewState(pSprite, &genDudeRecoilL); + if (inDuck(pXSprite->aiState) && Chance(rChance >> 2)) aiGenDudeNewState(pSprite, &genDudeRecoilD); + else if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeRecoilW); + else aiGenDudeNewState(pSprite, &genDudeRecoilL); } - short rState = inRecoil(pXSprite->aiState); + short rState = inRecoil(pXSprite->aiState); if (rState > 0) { if (!canWalk(pSprite)) { - if (rState == 1) pXSprite->aiState->nextState = &genDudeChaseNoWalkL; - else if (rState == 2) pXSprite->aiState->nextState = &genDudeChaseNoWalkD; - else pXSprite->aiState->nextState = &genDudeChaseNoWalkW; + if (rState == 1) pXSprite->aiState->nextState = &genDudeChaseNoWalkL; + else if (rState == 2) pXSprite->aiState->nextState = &genDudeChaseNoWalkD; + else pXSprite->aiState->nextState = &genDudeChaseNoWalkW; } else if (!dudeIsMelee(pXSprite) || Chance(rChance >> 2)) { - if (rState == 1) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeL : &genDudeDodgeShortL); - else if (rState == 2) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeD : &genDudeDodgeShortD); - else if (rState == 3) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeW : &genDudeDodgeShortW); - } - else if (rState == 1) pXSprite->aiState->nextState = &genDudeChaseL; - else if (rState == 2) pXSprite->aiState->nextState = &genDudeChaseD; - else pXSprite->aiState->nextState = &genDudeChaseW; + if (rState == 1) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeL : &genDudeDodgeShortL); + else if (rState == 2) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeD : &genDudeDodgeShortD); + else if (rState == 3) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeW : &genDudeDodgeShortW); + } + else if (rState == 1) pXSprite->aiState->nextState = &genDudeChaseL; + else if (rState == 2) pXSprite->aiState->nextState = &genDudeChaseD; + else pXSprite->aiState->nextState = &genDudeChaseW; - playGenDudeSound(pSprite, kGenDudeSndGotHit); + playGenDudeSound(pSprite, kGenDudeSndGotHit); - } + } - pDudeExtra->teslaHit = 0; - break; - } + pDudeExtra->teslaHit = 0; + break; + } #endif - case kDudeCultistTommy: - case kDudeCultistShotgun: - case kDudeCultistTesla: - case kDudeCultistTNT: - case kDudeCultistBeast: + case kDudeCultistTommy: + case kDudeCultistShotgun: + case kDudeCultistTesla: + case kDudeCultistTNT: + case kDudeCultistBeast: if (pSprite->type == kDudeCultistTommy) aiPlay3DSound(actor, 4013 + Random(2), AI_SFX_PRIORITY_2, -1); else aiPlay3DSound(actor, 1013 + Random(2), AI_SFX_PRIORITY_2, -1); if (!v4 && pXSprite->medium == kMediumNormal) { - if (pDudeExtra->teslaHit) aiNewState(actor, &cultistTeslaRecoil); - else aiNewState(actor, &cultistRecoil); + if (pDudeExtra->teslaHit) aiNewState(actor, &cultistTeslaRecoil); + else aiNewState(actor, &cultistRecoil); } else if (v4 && pXSprite->medium == kMediumNormal) { - if (pDudeExtra->teslaHit) aiNewState(actor, &cultistTeslaRecoil); - else if (gGameOptions.nDifficulty > 0) aiNewState(actor, &cultistProneRecoil); - else aiNewState(actor, &cultistRecoil); - } - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSwimRecoil); - else - { - if (pDudeExtra->teslaHit) - aiNewState(actor, &cultistTeslaRecoil); - else - aiNewState(actor, &cultistRecoil); - } - break; - case kDudeBurningCultist: - aiNewState(actor, &cultistBurnGoto); - break; + if (pDudeExtra->teslaHit) aiNewState(actor, &cultistTeslaRecoil); + else if (gGameOptions.nDifficulty > 0) aiNewState(actor, &cultistProneRecoil); + else aiNewState(actor, &cultistRecoil); + } + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSwimRecoil); + else + { + if (pDudeExtra->teslaHit) + aiNewState(actor, &cultistTeslaRecoil); + else + aiNewState(actor, &cultistRecoil); + } + break; + case kDudeBurningCultist: + aiNewState(actor, &cultistBurnGoto); + break; #ifdef NOONE_EXTENSIONS - case kDudeModernCustomBurning: - aiGenDudeNewState(pSprite, &genDudeBurnGoto); - break; + case kDudeModernCustomBurning: + aiGenDudeNewState(pSprite, &genDudeBurnGoto); + break; #endif - case kDudeZombieButcher: - aiPlay3DSound(actor, 1202, AI_SFX_PRIORITY_2, -1); - if (pDudeExtra->teslaHit) - aiNewState(actor, &zombieFTeslaRecoil); - else - aiNewState(actor, &zombieFRecoil); - break; - case kDudeZombieAxeNormal: - case kDudeZombieAxeBuried: - aiPlay3DSound(actor, 1106, AI_SFX_PRIORITY_2, -1); - if (pDudeExtra->teslaHit && pXSprite->data3 > pDudeInfo->startHealth/3) - aiNewState(actor, &zombieATeslaRecoil); + case kDudeZombieButcher: + aiPlay3DSound(actor, 1202, AI_SFX_PRIORITY_2, -1); + if (pDudeExtra->teslaHit) + aiNewState(actor, &zombieFTeslaRecoil); + else + aiNewState(actor, &zombieFRecoil); + break; + case kDudeZombieAxeNormal: + case kDudeZombieAxeBuried: + aiPlay3DSound(actor, 1106, AI_SFX_PRIORITY_2, -1); + if (pDudeExtra->teslaHit && pXSprite->data3 > pDudeInfo->startHealth / 3) + aiNewState(actor, &zombieATeslaRecoil); else if (pXSprite->data3 > pDudeInfo->startHealth / 3) - aiNewState(actor, &zombieARecoil2); - else - aiNewState(actor, &zombieARecoil); - break; - case kDudeBurningZombieAxe: - aiPlay3DSound(actor, 1106, AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &zombieABurnGoto); - break; - case kDudeBurningZombieButcher: - aiPlay3DSound(actor, 1202, AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &zombieFBurnGoto); - break; - case kDudeGargoyleFlesh: - case kDudeGargoyleStone: - aiPlay3DSound(actor, 1402, AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &gargoyleFRecoil); - break; - case kDudeCerberusTwoHead: - aiPlay3DSound(actor, 2302+Random(2), AI_SFX_PRIORITY_2, -1); - if (pDudeExtra->teslaHit && pXSprite->data3 > pDudeInfo->startHealth/3) - aiNewState(actor, &cerberusTeslaRecoil); - else - aiNewState(actor, &cerberusRecoil); - break; - case kDudeCerberusOneHead: + aiNewState(actor, &zombieARecoil2); + else + aiNewState(actor, &zombieARecoil); + break; + case kDudeBurningZombieAxe: + aiPlay3DSound(actor, 1106, AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &zombieABurnGoto); + break; + case kDudeBurningZombieButcher: + aiPlay3DSound(actor, 1202, AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &zombieFBurnGoto); + break; + case kDudeGargoyleFlesh: + case kDudeGargoyleStone: + aiPlay3DSound(actor, 1402, AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &gargoyleFRecoil); + break; + case kDudeCerberusTwoHead: aiPlay3DSound(actor, 2302 + Random(2), AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &cerberus2Recoil); - break; - case kDudeHellHound: - aiPlay3DSound(actor, 1302, AI_SFX_PRIORITY_2, -1); - if (pDudeExtra->teslaHit) - aiNewState(actor, &houndTeslaRecoil); - else - aiNewState(actor, &houndRecoil); - break; - case kDudeTchernobog: + if (pDudeExtra->teslaHit && pXSprite->data3 > pDudeInfo->startHealth / 3) + aiNewState(actor, &cerberusTeslaRecoil); + else + aiNewState(actor, &cerberusRecoil); + break; + case kDudeCerberusOneHead: + aiPlay3DSound(actor, 2302 + Random(2), AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &cerberus2Recoil); + break; + case kDudeHellHound: + aiPlay3DSound(actor, 1302, AI_SFX_PRIORITY_2, -1); + if (pDudeExtra->teslaHit) + aiNewState(actor, &houndTeslaRecoil); + else + aiNewState(actor, &houndRecoil); + break; + case kDudeTchernobog: aiPlay3DSound(actor, 2370 + Random(2), AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &tchernobogRecoil); - break; - case kDudeHand: - aiPlay3DSound(actor, 1902, AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &handRecoil); - break; - case kDudeRat: - aiPlay3DSound(actor, 2102, AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &ratRecoil); - break; - case kDudeBat: - aiPlay3DSound(actor, 2002, AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &batRecoil); - break; - case kDudeBoneEel: - aiPlay3DSound(actor, 1502, AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &eelRecoil); - break; - case kDudeGillBeast: { + aiNewState(actor, &tchernobogRecoil); + break; + case kDudeHand: + aiPlay3DSound(actor, 1902, AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &handRecoil); + break; + case kDudeRat: + aiPlay3DSound(actor, 2102, AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &ratRecoil); + break; + case kDudeBat: + aiPlay3DSound(actor, 2002, AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &batRecoil); + break; + case kDudeBoneEel: + aiPlay3DSound(actor, 1502, AI_SFX_PRIORITY_2, -1); + aiNewState(actor, &eelRecoil); + break; + case kDudeGillBeast: { XSECTOR* pXSector = NULL; - if (sector[pSprite->sectnum].extra > 0) - pXSector = &xsector[sector[pSprite->sectnum].extra]; - aiPlay3DSound(actor, 1702, AI_SFX_PRIORITY_2, -1); - if (pXSector && pXSector->Underwater) - aiNewState(actor, &gillBeastSwimRecoil); - else - aiNewState(actor, &gillBeastRecoil); - break; - } - case kDudePhantasm: - aiPlay3DSound(actor, 1602, AI_SFX_PRIORITY_2, -1); - if (pDudeExtra->teslaHit) - aiNewState(actor, &ghostTeslaRecoil); - else - aiNewState(actor, &ghostRecoil); - break; - case kDudeSpiderBrown: - case kDudeSpiderRed: - case kDudeSpiderBlack: + if (sector[pSprite->sectnum].extra > 0) + pXSector = &xsector[sector[pSprite->sectnum].extra]; + aiPlay3DSound(actor, 1702, AI_SFX_PRIORITY_2, -1); + if (pXSector && pXSector->Underwater) + aiNewState(actor, &gillBeastSwimRecoil); + else + aiNewState(actor, &gillBeastRecoil); + break; + } + case kDudePhantasm: + aiPlay3DSound(actor, 1602, AI_SFX_PRIORITY_2, -1); + if (pDudeExtra->teslaHit) + aiNewState(actor, &ghostTeslaRecoil); + else + aiNewState(actor, &ghostRecoil); + break; + case kDudeSpiderBrown: + case kDudeSpiderRed: + case kDudeSpiderBlack: aiPlay3DSound(actor, 1802 + Random(1), AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &spidDodge); - break; - case kDudeSpiderMother: + aiNewState(actor, &spidDodge); + break; + case kDudeSpiderMother: aiPlay3DSound(actor, 1851 + Random(1), AI_SFX_PRIORITY_2, -1); - aiNewState(actor, &spidDodge); - break; - case kDudeInnocent: + aiNewState(actor, &spidDodge); + break; + case kDudeInnocent: aiPlay3DSound(actor, 7007 + Random(2), AI_SFX_PRIORITY_2, -1); - if (pDudeExtra->teslaHit) - aiNewState(actor, &innocentTeslaRecoil); - else - aiNewState(actor, &innocentRecoil); - break; - case kDudeTinyCaleb: - if (pXSprite->medium == kMediumNormal) - { - if (pDudeExtra->teslaHit) - aiNewState(actor, &tinycalebTeslaRecoil); - else - aiNewState(actor, &tinycalebRecoil); - } - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &tinycalebSwimRecoil); - else - { - if (pDudeExtra->teslaHit) - aiNewState(actor, &tinycalebTeslaRecoil); - else - aiNewState(actor, &tinycalebRecoil); - } - break; - case kDudeBeast: + if (pDudeExtra->teslaHit) + aiNewState(actor, &innocentTeslaRecoil); + else + aiNewState(actor, &innocentRecoil); + break; + case kDudeTinyCaleb: + if (pXSprite->medium == kMediumNormal) + { + if (pDudeExtra->teslaHit) + aiNewState(actor, &tinycalebTeslaRecoil); + else + aiNewState(actor, &tinycalebRecoil); + } + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &tinycalebSwimRecoil); + else + { + if (pDudeExtra->teslaHit) + aiNewState(actor, &tinycalebTeslaRecoil); + else + aiNewState(actor, &tinycalebRecoil); + } + break; + case kDudeBeast: aiPlay3DSound(actor, 9004 + Random(2), AI_SFX_PRIORITY_2, -1); - if (pXSprite->medium == kMediumNormal) - { - if (pDudeExtra->teslaHit) - aiNewState(actor, &beastTeslaRecoil); - else - aiNewState(actor, &beastRecoil); - } - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &beastSwimRecoil); - else - { - if (pDudeExtra->teslaHit) - aiNewState(actor, &beastTeslaRecoil); - else - aiNewState(actor, &beastRecoil); - } - break; - case kDudePodGreen: - case kDudePodFire: - aiNewState(actor, &podRecoil); - break; - case kDudeTentacleGreen: - case kDudeTentacleFire: - aiNewState(actor, &tentacleRecoil); - break; - default: - aiNewState(actor, &genRecoil); - break; - } - pDudeExtra->teslaHit = 0; - } + if (pXSprite->medium == kMediumNormal) + { + if (pDudeExtra->teslaHit) + aiNewState(actor, &beastTeslaRecoil); + else + aiNewState(actor, &beastRecoil); + } + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &beastSwimRecoil); + else + { + if (pDudeExtra->teslaHit) + aiNewState(actor, &beastTeslaRecoil); + else + aiNewState(actor, &beastRecoil); + } + break; + case kDudePodGreen: + case kDudePodFire: + aiNewState(actor, &podRecoil); + break; + case kDudeTentacleGreen: + case kDudeTentacleFire: + aiNewState(actor, &tentacleRecoil); + break; + default: + aiNewState(actor, &genRecoil); + break; + } + pDudeExtra->teslaHit = 0; + } } //--------------------------------------------------------------------------- @@ -1525,44 +1525,44 @@ void RecoilDude(DBloodActor* actor) void aiThinkTarget(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); - if (Chance(pDudeInfo->alertChance)) - { - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { + if (Chance(pDudeInfo->alertChance)) + { + for (int p = connecthead; p >= 0; p = connectpoint2[p]) + { PLAYER* pPlayer = &gPlayer[p]; - if (pSprite->owner == 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; + if (pSprite->owner == 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; + 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; + 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); - return; - } - else if (nDist < pDudeInfo->hearDist) - { - aiSetTarget(actor, x, y, z); - aiActivateDude(actor); - return; - } - } - } + if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) + { + aiSetTarget(actor, pPlayer->actor()); + aiActivateDude(actor); + return; + } + else if (nDist < pDudeInfo->hearDist) + { + aiSetTarget(actor, x, y, z); + aiActivateDude(actor); + return; + } + } + } } //--------------------------------------------------------------------------- @@ -1575,65 +1575,65 @@ void aiLookForTarget(DBloodActor* actor) { auto pSprite = &actor->s(); auto pXSprite = &actor->x(); - assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); + assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); - if (Chance(pDudeInfo->alertChance)) - { - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { + if (Chance(pDudeInfo->alertChance)) + { + for (int p = connecthead; p >= 0; p = connectpoint2[p]) + { PLAYER* pPlayer = &gPlayer[p]; - if (pSprite->owner == 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; + if (pSprite->owner == 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; + 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; + 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); - return; - } - else if (nDist < pDudeInfo->hearDist) - { - aiSetTarget(actor, x, y, z); - aiActivateDude(actor); - return; - } - } - if (pXSprite->state) - { - uint8_t sectmap[(kMaxSectors+7)>>3]; - const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic - GetClosestSpriteSectors(pSprite->sectnum, pSprite->x, pSprite->y, 400, sectmap, nullptr, newSectCheckMethod); + if (nDist < pDudeInfo->seeDist && abs(nDeltaAngle) <= pDudeInfo->periphery) + { + aiSetTarget(actor, pPlayer->actor()); + aiActivateDude(actor); + return; + } + else if (nDist < pDudeInfo->hearDist) + { + aiSetTarget(actor, x, y, z); + aiActivateDude(actor); + return; + } + } + if (pXSprite->state) + { + uint8_t sectmap[(kMaxSectors + 7) >> 3]; + const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic + GetClosestSpriteSectors(pSprite->sectnum, pSprite->x, pSprite->y, 400, sectmap, nullptr, newSectCheckMethod); - BloodStatIterator it(kStatDude); - while (DBloodActor* actor2 = it.Next()) - { + BloodStatIterator it(kStatDude); + while (DBloodActor* actor2 = it.Next()) + { spritetype* pSprite2 = &actor2->s(); int dx = pSprite2->x - pSprite->x; int dy = pSprite2->y - pSprite->y; - int nDist = approxDist(dx, dy); - if (pSprite2->type == kDudeInnocent) - { + int nDist = approxDist(dx, dy); + if (pSprite2->type == kDudeInnocent) + { DUDEINFO* pDudeInfo = getDudeInfo(pSprite2->type); - if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist) - continue; - aiSetTarget(actor, actor2); - aiActivateDude(actor); - return; - } - } - } - } + if (nDist > pDudeInfo->seeDist && nDist > pDudeInfo->hearDist) + continue; + aiSetTarget(actor, actor2); + aiActivateDude(actor); + return; + } + } + } + } } //--------------------------------------------------------------------------- @@ -1644,58 +1644,58 @@ void aiLookForTarget(DBloodActor* actor) void aiProcessDudes(void) { - BloodStatIterator it(kStatDude); - while (auto actor = it.Next()) - { + BloodStatIterator it(kStatDude); + while (auto actor = it.Next()) + { auto pSprite = &actor->s(); - if (pSprite->flags & 32) continue; + if (pSprite->flags & 32) continue; auto pXSprite = &actor->x(); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); - if (IsPlayerSprite(pSprite) || pXSprite->health == 0) continue; + if (IsPlayerSprite(pSprite) || pXSprite->health == 0) continue; pXSprite->stateTimer = ClipLow(pXSprite->stateTimer - 4, 0); - if (pXSprite->aiState && pXSprite->aiState->moveFunc) - pXSprite->aiState->moveFunc(actor); + if (pXSprite->aiState && pXSprite->aiState->moveFunc) + pXSprite->aiState->moveFunc(actor); - if (pXSprite->aiState->thinkFunc && (gFrameCount & 3) == (pSprite->index & 3)) // ouch, ouch! :( - pXSprite->aiState->thinkFunc(actor); + if (pXSprite->aiState->thinkFunc && (gFrameCount & 3) == (pSprite->index & 3)) // ouch, ouch! :( + pXSprite->aiState->thinkFunc(actor); - switch (pSprite->type) { + switch (pSprite->type) { #ifdef NOONE_EXTENSIONS - case kDudeModernCustom: - case kDudeModernCustomBurning: { - GENDUDEEXTRA* pExtra = &gGenDudeExtra[pSprite->index]; - if (pExtra->slaveCount > 0) updateTargetOfSlaves(pSprite); - if (pExtra->nLifeLeech >= 0) updateTargetOfLeech(pSprite); - if (pXSprite->stateTimer == 0 && pXSprite->aiState && pXSprite->aiState->nextState + case kDudeModernCustom: + case kDudeModernCustomBurning: { + GENDUDEEXTRA* pExtra = &gGenDudeExtra[pSprite->index]; + if (pExtra->slaveCount > 0) updateTargetOfSlaves(pSprite); + if (pExtra->nLifeLeech >= 0) updateTargetOfLeech(pSprite); + if (pXSprite->stateTimer == 0 && pXSprite->aiState && pXSprite->aiState->nextState && (pXSprite->aiState->stateTicks > 0 || seqGetStatus(3, pSprite->extra) < 0)) - { - aiGenDudeNewState(pSprite, pXSprite->aiState->nextState); - } - int hinder = ((pExtra->isMelee) ? 25 : 5) << 4; - if (pXSprite->health <= 0 || hinder > actor->cumulDamage) break; - pXSprite->data3 = actor->cumulDamage; - RecoilDude(actor); - break; - } + { + aiGenDudeNewState(pSprite, pXSprite->aiState->nextState); + } + int hinder = ((pExtra->isMelee) ? 25 : 5) << 4; + if (pXSprite->health <= 0 || hinder > actor->cumulDamage) break; + pXSprite->data3 = actor->cumulDamage; + RecoilDude(actor); + break; + } #endif - default: - if (pXSprite->stateTimer == 0 && pXSprite->aiState && pXSprite->aiState->nextState) { - if (pXSprite->aiState->stateTicks > 0) - aiNewState(actor, pXSprite->aiState->nextState); - else if (seqGetStatus(actor) < 0) - aiNewState(actor, pXSprite->aiState->nextState); - } + default: + if (pXSprite->stateTimer == 0 && pXSprite->aiState && pXSprite->aiState->nextState) { + if (pXSprite->aiState->stateTicks > 0) + aiNewState(actor, pXSprite->aiState->nextState); + else if (seqGetStatus(actor) < 0) + aiNewState(actor, pXSprite->aiState->nextState); + } if (pXSprite->health > 0 && ((pDudeInfo->hinderDamage << 4) <= actor->cumulDamage)) - { - pXSprite->data3 = actor->cumulDamage; - RecoilDude(actor); - } - break; - } - } + { + pXSprite->data3 = actor->cumulDamage; + RecoilDude(actor); + } + break; + } + } it.Reset(kStatDude); while (auto actor = it.Next()) @@ -1708,285 +1708,285 @@ void aiInit(void) { BloodStatIterator it(kStatDude); while (auto actor = it.Next()) - { + { aiInitSprite(actor); - } + } } void aiInitSprite(DBloodActor* actor) { auto pSprite = &actor->s(); auto pXSprite = &actor->x(); - int nSector = pSprite->sectnum; - int nXSector = sector[nSector].extra; + int nSector = pSprite->sectnum; + int nXSector = sector[nSector].extra; XSECTOR* pXSector = NULL; - if (nXSector > 0) - pXSector = &xsector[nXSector]; + if (nXSector > 0) + pXSector = &xsector[nXSector]; DUDEEXTRA* pDudeExtra = &actor->dudeExtra; - DUDEEXTRA_STATS *pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtra->teslaHit = 0; - pDudeExtra->time = 0; - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 0; - - #ifdef NOONE_EXTENSIONS + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtra->teslaHit = 0; + pDudeExtra->time = 0; + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 0; + +#ifdef NOONE_EXTENSIONS int stateTimer = -1; - int targetX = 0, targetY = 0, targetZ = 0; + int targetX = 0, targetY = 0, targetZ = 0; DBloodActor* pTargetMarker = nullptr; - // dude patrol init + // dude patrol init if (gModernMap) { - // must keep it in case of loading save - if (pXSprite->dudeFlag4 && actor->GetTarget() && actor->GetTarget()->s().type == kMarkerPath) + // must keep it in case of loading save + if (pXSprite->dudeFlag4 && actor->GetTarget() && actor->GetTarget()->s().type == kMarkerPath) { - stateTimer = pXSprite->stateTimer; + stateTimer = pXSprite->stateTimer; pTargetMarker = actor->GetTarget(); - targetX = pXSprite->targetX; + targetX = pXSprite->targetX; targetY = pXSprite->targetY; - targetZ = pXSprite->targetZ; - } - } + targetZ = pXSprite->targetZ; + } + } #endif switch (pSprite->type) { - case kDudeCultistTommy: - case kDudeCultistShotgun: - case kDudeCultistTesla: - case kDudeCultistTNT: - case kDudeCultistBeast: - { - pDudeExtraE->active = 0; - aiNewState(actor, &cultistIdle); - break; - } - case kDudeCultistTommyProne: - { - pDudeExtraE->active = 0; - aiNewState(actor, &fanaticProneIdle); - break; - } - case kDudeCultistShotgunProne: - { - pDudeExtraE->active = 0; - aiNewState(actor, &cultistProneIdle); - break; - } - case kDudeZombieButcher: { - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &zombieFIdle); - break; - } - case kDudeZombieAxeNormal: { - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &zombieAIdle); - break; - } - case kDudeZombieAxeLaying: - { - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &zombieSIdle); - pSprite->flags &= ~1; - break; - } - case kDudeZombieAxeBuried: { - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &zombieEIdle); - break; - } - case kDudeGargoyleFlesh: - case kDudeGargoyleStone: { - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 0; - aiNewState(actor, &gargoyleFIdle); - break; - } - case kDudeGargoyleStatueFlesh: - case kDudeGargoyleStatueStone: - aiNewState(actor, &gargoyleStatueIdle); - break; - case kDudeCerberusTwoHead: { - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &cerberusIdle); - break; - } - case kDudeCerberusOneHead: { - if (!VanillaMode()) { - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &cerberus2Idle); - break; - } - aiNewState(actor, &genIdle); - break; - } - case kDudeHellHound: - aiNewState(actor, &houndIdle); - break; - case kDudeHand: - aiNewState(actor, &handIdle); - break; - case kDudePhantasm: - { - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 0; - aiNewState(actor, &ghostIdle); - break; - } - case kDudeInnocent: - aiNewState(actor, &innocentIdle); - break; - case kDudeRat: - aiNewState(actor, &ratIdle); - break; - case kDudeBoneEel: - { - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 0; - aiNewState(actor, &eelIdle); - break; - } - case kDudeGillBeast: - aiNewState(actor, &gillBeastIdle); - break; - case kDudeBat: - { - pDudeExtraE->thinkTime = 0; - pDudeExtraE->active = 0; - aiNewState(actor, &batIdle); - break; - } - case kDudeSpiderBrown: - case kDudeSpiderRed: - case kDudeSpiderBlack: - { - pDudeExtraE->active = 0; - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &spidIdle); - break; - } - case kDudeSpiderMother: - { - pDudeExtraE->active = 0; - pDudeExtraE->birthCounter = 0; - aiNewState(actor, &spidIdle); - break; - } - case kDudeTchernobog: - { - pDudeExtraE->active = 0; - pDudeExtraE->thinkTime = 0; - aiNewState(actor, &tchernobogIdle); - break; - } - case kDudeTinyCaleb: - aiNewState(actor, &tinycalebIdle); - break; - case kDudeBeast: - aiNewState(actor, &beastIdle); - break; - case kDudePodGreen: - case kDudePodFire: - aiNewState(actor, &podIdle); - break; - case kDudeTentacleGreen: - case kDudeTentacleFire: - aiNewState(actor, &tentacleIdle); - break; + case kDudeCultistTommy: + case kDudeCultistShotgun: + case kDudeCultistTesla: + case kDudeCultistTNT: + case kDudeCultistBeast: + { + pDudeExtraE->active = 0; + aiNewState(actor, &cultistIdle); + break; + } + case kDudeCultistTommyProne: + { + pDudeExtraE->active = 0; + aiNewState(actor, &fanaticProneIdle); + break; + } + case kDudeCultistShotgunProne: + { + pDudeExtraE->active = 0; + aiNewState(actor, &cultistProneIdle); + break; + } + case kDudeZombieButcher: { + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &zombieFIdle); + break; + } + case kDudeZombieAxeNormal: { + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &zombieAIdle); + break; + } + case kDudeZombieAxeLaying: + { + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &zombieSIdle); + pSprite->flags &= ~1; + break; + } + case kDudeZombieAxeBuried: { + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &zombieEIdle); + break; + } + case kDudeGargoyleFlesh: + case kDudeGargoyleStone: { + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 0; + aiNewState(actor, &gargoyleFIdle); + break; + } + case kDudeGargoyleStatueFlesh: + case kDudeGargoyleStatueStone: + aiNewState(actor, &gargoyleStatueIdle); + break; + case kDudeCerberusTwoHead: { + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &cerberusIdle); + break; + } + case kDudeCerberusOneHead: { + if (!VanillaMode()) { + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &cerberus2Idle); + break; + } + aiNewState(actor, &genIdle); + break; + } + case kDudeHellHound: + aiNewState(actor, &houndIdle); + break; + case kDudeHand: + aiNewState(actor, &handIdle); + break; + case kDudePhantasm: + { + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 0; + aiNewState(actor, &ghostIdle); + break; + } + case kDudeInnocent: + aiNewState(actor, &innocentIdle); + break; + case kDudeRat: + aiNewState(actor, &ratIdle); + break; + case kDudeBoneEel: + { + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 0; + aiNewState(actor, &eelIdle); + break; + } + case kDudeGillBeast: + aiNewState(actor, &gillBeastIdle); + break; + case kDudeBat: + { + pDudeExtraE->thinkTime = 0; + pDudeExtraE->active = 0; + aiNewState(actor, &batIdle); + break; + } + case kDudeSpiderBrown: + case kDudeSpiderRed: + case kDudeSpiderBlack: + { + pDudeExtraE->active = 0; + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &spidIdle); + break; + } + case kDudeSpiderMother: + { + pDudeExtraE->active = 0; + pDudeExtraE->birthCounter = 0; + aiNewState(actor, &spidIdle); + break; + } + case kDudeTchernobog: + { + pDudeExtraE->active = 0; + pDudeExtraE->thinkTime = 0; + aiNewState(actor, &tchernobogIdle); + break; + } + case kDudeTinyCaleb: + aiNewState(actor, &tinycalebIdle); + break; + case kDudeBeast: + aiNewState(actor, &beastIdle); + break; + case kDudePodGreen: + case kDudePodFire: + aiNewState(actor, &podIdle); + break; + case kDudeTentacleGreen: + case kDudeTentacleFire: + aiNewState(actor, &tentacleIdle); + break; #ifdef NOONE_EXTENSIONS - case kDudeModernCustom: - case kDudeModernCustomBurning: - if (!gModernMap) break; - aiGenDudeInitSprite(pSprite, pXSprite); - genDudePrepare(pSprite, kGenDudePropertyAll); - break; + case kDudeModernCustom: + case kDudeModernCustomBurning: + if (!gModernMap) break; + aiGenDudeInitSprite(pSprite, pXSprite); + genDudePrepare(pSprite, kGenDudePropertyAll); + break; #endif - default: - aiNewState(actor, &genIdle); - break; - } + default: + aiNewState(actor, &genIdle); + break; + } aiSetTarget(actor, 0, 0, 0); - pXSprite->stateTimer = 0; - switch (pSprite->type) - { - case kDudeSpiderBrown: - case kDudeSpiderRed: - case kDudeSpiderBlack: + pXSprite->stateTimer = 0; + switch (pSprite->type) + { + case kDudeSpiderBrown: + case kDudeSpiderRed: + case kDudeSpiderBlack: if (pSprite->cstat & 8) pSprite->flags |= 9; - else pSprite->flags = 15; - break; - case kDudeGargoyleFlesh: - case kDudeGargoyleStone: - case kDudePhantasm: - case kDudeBoneEel: - case kDudeBat: - pSprite->flags |= 9; - break; - case kDudeGillBeast: - if (pXSector && pXSector->Underwater) pSprite->flags |= 9; - else pSprite->flags = 15; - break; - case kDudeZombieAxeBuried: - case kDudeZombieAxeLaying: - pSprite->flags = 7; - break; + else pSprite->flags = 15; + break; + case kDudeGargoyleFlesh: + case kDudeGargoyleStone: + case kDudePhantasm: + case kDudeBoneEel: + case kDudeBat: + pSprite->flags |= 9; + break; + case kDudeGillBeast: + if (pXSector && pXSector->Underwater) pSprite->flags |= 9; + else pSprite->flags = 15; + break; + case kDudeZombieAxeBuried: + case kDudeZombieAxeLaying: + pSprite->flags = 7; + break; #ifdef NOONE_EXTENSIONS - case kDudePodMother: // FakeDude type - if (gModernMap) break; - [[fallthrough]]; - // Allow put pods and tentacles on ceilings if sprite is y-flipped. - case kDudePodGreen: - case kDudeTentacleGreen: - case kDudePodFire: - case kDudeTentacleFire: - case kDudeTentacleMother: - if (gModernMap && (pSprite->cstat & CSTAT_SPRITE_YFLIP)) { - if (!(pSprite->flags & kModernTypeFlag1)) // don't add autoaim for player if hitag 1 specified in editor. - pSprite->flags = kHitagAutoAim; - break; - } - [[fallthrough]]; - // go default + case kDudePodMother: // FakeDude type + if (gModernMap) break; + [[fallthrough]]; + // Allow put pods and tentacles on ceilings if sprite is y-flipped. + case kDudePodGreen: + case kDudeTentacleGreen: + case kDudePodFire: + case kDudeTentacleFire: + case kDudeTentacleMother: + if (gModernMap && (pSprite->cstat & CSTAT_SPRITE_YFLIP)) { + if (!(pSprite->flags & kModernTypeFlag1)) // don't add autoaim for player if hitag 1 specified in editor. + pSprite->flags = kHitagAutoAim; + break; + } + [[fallthrough]]; + // go default #endif - default: - pSprite->flags = 15; - break; - } + default: + pSprite->flags = 15; + break; + } #ifdef NOONE_EXTENSIONS if (gModernMap) { if (pXSprite->dudeFlag4) { - // restore dude's path + // restore dude's path if (pTargetMarker) { actor->SetTarget(pTargetMarker); - pXSprite->targetX = targetX; - pXSprite->targetY = targetY; - pXSprite->targetZ = targetZ; - } + pXSprite->targetX = targetX; + pXSprite->targetY = targetY; + pXSprite->targetZ = targetZ; + } - // reset target spot progress - pXSprite->data3 = 0; + // reset target spot progress + pXSprite->data3 = 0; - // make dude follow the markers - bool uwater = spriteIsUnderwater(pSprite); - if (pXSprite->target_i <= 0 || sprite[pXSprite->target_i].type != kMarkerPath) { - pXSprite->target_i = -1; aiPatrolSetMarker(pSprite, pXSprite); - } + // make dude follow the markers + bool uwater = spriteIsUnderwater(pSprite); + if (pXSprite->target_i <= 0 || sprite[pXSprite->target_i].type != kMarkerPath) { + pXSprite->target_i = -1; aiPatrolSetMarker(pSprite, pXSprite); + } - if (stateTimer > 0) { - if (uwater) aiPatrolState(pSprite, kAiStatePatrolWaitW); - else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(pSprite, kAiStatePatrolWaitC); - else aiPatrolState(pSprite, kAiStatePatrolWaitL); - pXSprite->stateTimer = stateTimer; // restore state timer - } - else if (uwater) aiPatrolState(pSprite, kAiStatePatrolMoveW); - else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(pSprite, kAiStatePatrolMoveC); - else aiPatrolState(pSprite, kAiStatePatrolMoveL); - } - } + if (stateTimer > 0) { + if (uwater) aiPatrolState(pSprite, kAiStatePatrolWaitW); + else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(pSprite, kAiStatePatrolWaitC); + else aiPatrolState(pSprite, kAiStatePatrolWaitL); + pXSprite->stateTimer = stateTimer; // restore state timer + } + else if (uwater) aiPatrolState(pSprite, kAiStatePatrolMoveW); + else if (pXSprite->unused1 & kDudeFlagCrouch) aiPatrolState(pSprite, kAiStatePatrolMoveC); + else aiPatrolState(pSprite, kAiStatePatrolMoveL); + } + } #endif } diff --git a/source/games/blood/src/aibat.cpp b/source/games/blood/src/aibat.cpp index 934227270..aa450b15c 100644 --- a/source/games/blood/src/aibat.cpp +++ b/source/games/blood/src/aibat.cpp @@ -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 diff --git a/source/games/blood/src/aibeast.cpp b/source/games/blood/src/aibeast.cpp index 0f157a1b6..62d424095 100644 --- a/source/games/blood/src/aibeast.cpp +++ b/source/games/blood/src/aibeast.cpp @@ -30,19 +30,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -static void MorphToBeast(DBloodActor *); -static void beastThinkSearch(DBloodActor *); -static void beastThinkGoto(DBloodActor *); -static void beastThinkChase(DBloodActor *); -static void beastThinkSwimGoto(DBloodActor *); -static void beastThinkSwimChase(DBloodActor *); -static void beastMoveForward(DBloodActor *); -static void sub_628A0(DBloodActor *); -static void sub_62AE0(DBloodActor *); -static void sub_62D7C(DBloodActor *); +static void MorphToBeast(DBloodActor*); +static void beastThinkSearch(DBloodActor*); +static void beastThinkGoto(DBloodActor*); +static void beastThinkChase(DBloodActor*); +static void beastThinkSwimGoto(DBloodActor*); +static void beastThinkSwimChase(DBloodActor*); +static void beastMoveForward(DBloodActor*); +static void sub_628A0(DBloodActor*); +static void sub_62AE0(DBloodActor*); +static void sub_62D7C(DBloodActor*); -AISTATE beastIdle = {kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; -AISTATE beastChase = {kAiStateChase, 8, -1, 0, NULL, beastMoveForward, beastThinkChase, NULL }; +AISTATE beastIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; +AISTATE beastChase = { kAiStateChase, 8, -1, 0, NULL, beastMoveForward, beastThinkChase, NULL }; AISTATE beastDodge = { kAiStateMove, 8, -1, 60, NULL, aiMoveDodge, NULL, &beastChase }; AISTATE beastGoto = { kAiStateMove, 8, -1, 600, NULL, beastMoveForward, beastThinkGoto, &beastIdle }; AISTATE beastSlash = { kAiStateChase, 6, nSlashClient, 120, NULL, NULL, NULL, &beastChase }; @@ -50,7 +50,7 @@ AISTATE beastStomp = { kAiStateChase, 7, nStompClient, 120, NULL, NULL, NULL, &b AISTATE beastSearch = { kAiStateSearch, 8, -1, 120, NULL, beastMoveForward, beastThinkSearch, &beastIdle }; AISTATE beastRecoil = { kAiStateRecoil, 5, -1, 0, NULL, NULL, NULL, &beastDodge }; AISTATE beastTeslaRecoil = { kAiStateRecoil, 4, -1, 0, NULL, NULL, NULL, &beastDodge }; -AISTATE beastSwimIdle = {kAiStateIdle, 9, -1, 0, NULL, NULL, aiThinkTarget, NULL }; +AISTATE beastSwimIdle = { kAiStateIdle, 9, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE beastSwimChase = { kAiStateChase, 9, -1, 0, NULL, sub_628A0, beastThinkSwimChase, NULL }; AISTATE beastSwimDodge = { kAiStateMove, 9, -1, 90, NULL, aiMoveDodge, NULL, &beastSwimChase }; AISTATE beastSwimGoto = { kAiStateMove, 9, -1, 600, NULL, beastMoveForward, beastThinkSwimGoto, &beastSwimIdle }; @@ -65,519 +65,519 @@ AISTATE beast138FEC = { kAiStateOther, 9, -1, 120, NULL, aiMoveTurn, NULL, &beas void SlashSeqCallback(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); - // Correct ? - int dz = pSprite->z-pTarget->z; - dx += Random3(4000-700*gGameOptions.nDifficulty); - dy += Random3(4000-700*gGameOptions.nDifficulty); - actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); - actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); - actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); - sfxPlay3DSound(actor, 9012+Random(2), -1, 0); + 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); + // Correct ? + int dz = pSprite->z - pTarget->z; + dx += Random3(4000 - 700 * gGameOptions.nDifficulty); + dy += Random3(4000 - 700 * gGameOptions.nDifficulty); + actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); + actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); + actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); + sfxPlay3DSound(actor, 9012 + Random(2), -1, 0); } void StompSeqCallback(int, DBloodActor* actor1) { - uint8_t sectmap[(kMaxSectors+7)>>3]; - XSPRITE* pXSprite = &actor1->x(); - spritetype *pSprite = &actor1->s(); - int dx = CosScale16(pSprite->ang); - int dy = SinScale16(pSprite->ang); - int x = pSprite->x; - int y = pSprite->y; - int z = pSprite->z; - int vc = 400; - int nSector = pSprite->sectnum; - int v1c = 5+2*gGameOptions.nDifficulty; - int v10 = 25+30*gGameOptions.nDifficulty; - const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic - GetClosestSpriteSectors(nSector, x, y, vc, sectmap, nullptr, newSectCheckMethod); - char v4 = 0; - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - DBloodActor* actor2 = nullptr; - actHitcodeToData(hit, &gHitInfo, &actor2); - if (hit == 3 && actor2) - { - if (actor2->s().statnum == kStatDude) - v4 = 0; - } - vc <<= 4; - BloodStatIterator it1(kStatDude); - while (auto actor2 = it1.Next()) - { - if (actor1 != actor2 || v4) - { - spritetype *pSprite2 = &actor2->s(); - if (pSprite2->extra > 0 && pSprite2->extra < kMaxXSprites) - { - if (pSprite2->type == kDudeBeast) - continue; - if (pSprite2->flags&32) - continue; - if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) - { - int top, bottom; - GetActorExtents(actor1, &top, &bottom); - if (abs(bottom-sector[nSector].floorz) == 0) - { - int dx = abs(pSprite->x-pSprite2->x); - int dy = abs(pSprite->y-pSprite2->y); - int nDist2 = ksqrt(dx*dx + dy*dy); - if (nDist2 <= vc) - { - int nDamage; - if (!nDist2) - nDamage = v1c + v10; - else - nDamage = v1c + ((vc-nDist2)*v10)/vc; - if (IsPlayerSprite(pSprite2)) - gPlayer[pSprite2->type-kDudePlayer1].quakeEffect += nDamage*4; - actDamageSprite(actor1, actor2, kDamageFall, nDamage<<4); - } - } - } - } - } - } - it1.Reset(kStatThing); - while (auto actor2 = it1.Next()) - { - spritetype *pSprite2 = &actor2->s(); - if (pSprite2->flags&32) - continue; - if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) - { - XSPRITE *pXSprite = &actor2->x(); - if (pXSprite->locked) - continue; - int dx = abs(pSprite->x-pSprite2->x); - int dy = abs(pSprite->y-pSprite2->y); - int nDist2 = ksqrt(dx*dx + dy*dy); - if (nDist2 <= vc) - { - int nDamage; - if (!nDist2) - nDamage = v1c + v10; - else - nDamage = v1c + ((vc-nDist2)*v10)/vc; - if (IsPlayerSprite(pSprite2)) - gPlayer[pSprite2->type-kDudePlayer1].quakeEffect += nDamage*4; - actDamageSprite(actor1, actor2, kDamageFall, nDamage<<4); - } - } - } - sfxPlay3DSound(actor1, 9015+Random(2), -1, 0); + uint8_t sectmap[(kMaxSectors + 7) >> 3]; + XSPRITE* pXSprite = &actor1->x(); + spritetype* pSprite = &actor1->s(); + int dx = CosScale16(pSprite->ang); + int dy = SinScale16(pSprite->ang); + int x = pSprite->x; + int y = pSprite->y; + int z = pSprite->z; + int vc = 400; + int nSector = pSprite->sectnum; + int v1c = 5 + 2 * gGameOptions.nDifficulty; + int v10 = 25 + 30 * gGameOptions.nDifficulty; + const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic + GetClosestSpriteSectors(nSector, x, y, vc, sectmap, nullptr, newSectCheckMethod); + char v4 = 0; + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + DBloodActor* actor2 = nullptr; + actHitcodeToData(hit, &gHitInfo, &actor2); + if (hit == 3 && actor2) + { + if (actor2->s().statnum == kStatDude) + v4 = 0; + } + vc <<= 4; + BloodStatIterator it1(kStatDude); + while (auto actor2 = it1.Next()) + { + if (actor1 != actor2 || v4) + { + spritetype* pSprite2 = &actor2->s(); + if (pSprite2->extra > 0 && pSprite2->extra < kMaxXSprites) + { + if (pSprite2->type == kDudeBeast) + continue; + if (pSprite2->flags & 32) + continue; + if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) + { + int top, bottom; + GetActorExtents(actor1, &top, &bottom); + if (abs(bottom - sector[nSector].floorz) == 0) + { + int dx = abs(pSprite->x - pSprite2->x); + int dy = abs(pSprite->y - pSprite2->y); + int nDist2 = ksqrt(dx * dx + dy * dy); + if (nDist2 <= vc) + { + int nDamage; + if (!nDist2) + nDamage = v1c + v10; + else + nDamage = v1c + ((vc - nDist2) * v10) / vc; + if (IsPlayerSprite(pSprite2)) + gPlayer[pSprite2->type - kDudePlayer1].quakeEffect += nDamage * 4; + actDamageSprite(actor1, actor2, kDamageFall, nDamage << 4); + } + } + } + } + } + } + it1.Reset(kStatThing); + while (auto actor2 = it1.Next()) + { + spritetype* pSprite2 = &actor2->s(); + if (pSprite2->flags & 32) + continue; + if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) + { + XSPRITE* pXSprite = &actor2->x(); + if (pXSprite->locked) + continue; + int dx = abs(pSprite->x - pSprite2->x); + int dy = abs(pSprite->y - pSprite2->y); + int nDist2 = ksqrt(dx * dx + dy * dy); + if (nDist2 <= vc) + { + int nDamage; + if (!nDist2) + nDamage = v1c + v10; + else + nDamage = v1c + ((vc - nDist2) * v10) / vc; + if (IsPlayerSprite(pSprite2)) + gPlayer[pSprite2->type - kDudePlayer1].quakeEffect += nDamage * 4; + actDamageSprite(actor1, actor2, kDamageFall, nDamage << 4); + } + } + } + sfxPlay3DSound(actor1, 9015 + Random(2), -1, 0); } static void MorphToBeast(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - actHealDude(actor, dudeInfo[51].startHealth, dudeInfo[51].startHealth); - pSprite->type = kDudeBeast; + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + actHealDude(actor, dudeInfo[51].startHealth, dudeInfo[51].startHealth); + pSprite->type = kDudeBeast; } static void beastThinkSearch(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 beastThinkGoto(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, &beastSwimSearch); - else - aiNewState(actor, &beastSearch); - } - 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, &beastSwimSearch); + else + aiNewState(actor, &beastSearch); + } + aiThinkTarget(actor); } static void beastThinkChase(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, &beastSwimSearch); - else - aiNewState(actor, &beastSearch); - 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, &beastSwimSearch); - else - aiNewState(actor, &beastSearch); - 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, &beastSwimSearch); - else - aiNewState(actor, &beastSearch); - 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 < 0x1400 && nDist > 0xa00 && abs(nDeltaAngle) < 85 && (pTarget->flags&2) - && IsPlayerSprite(pTarget) && Chance(0x8000)) - { - 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); - if (pXTarget->health > (unsigned)gPlayerTemplate[0].startHealth/2) - { - switch (hit) - { - case -1: - if (!pXSector || !pXSector->Underwater) - aiNewState(actor, &beastStomp); - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type) - { - if (!pXSector || !pXSector->Underwater) - aiNewState(actor, &beastStomp); - } - else - { - if (pXSector && pXSector->Underwater) - aiNewState(actor, &beastSwimDodge); - else - aiNewState(actor, &beastDodge); - } - break; - default: - if (!pXSector || !pXSector->Underwater) - aiNewState(actor, &beastStomp); - break; - } - } - } - 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, &beastSwimSlash); - else - aiNewState(actor, &beastSlash); - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type) - { - if (pXSector && pXSector->Underwater) - aiNewState(actor, &beastSwimSlash); - else - aiNewState(actor, &beastSlash); - } - else - { - if (pXSector && pXSector->Underwater) - aiNewState(actor, &beastSwimDodge); - else - aiNewState(actor, &beastDodge); - } - break; - default: - if (pXSector && pXSector->Underwater) - aiNewState(actor, &beastSwimSlash); - else - aiNewState(actor, &beastSlash); - 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, &beastSwimSearch); + else + aiNewState(actor, &beastSearch); + 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, &beastSwimSearch); + else + aiNewState(actor, &beastSearch); + 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, &beastSwimSearch); + else + aiNewState(actor, &beastSearch); + 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 < 0x1400 && nDist > 0xa00 && abs(nDeltaAngle) < 85 && (pTarget->flags & 2) + && IsPlayerSprite(pTarget) && Chance(0x8000)) + { + 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); + if (pXTarget->health > (unsigned)gPlayerTemplate[0].startHealth / 2) + { + switch (hit) + { + case -1: + if (!pXSector || !pXSector->Underwater) + aiNewState(actor, &beastStomp); + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type) + { + if (!pXSector || !pXSector->Underwater) + aiNewState(actor, &beastStomp); + } + else + { + if (pXSector && pXSector->Underwater) + aiNewState(actor, &beastSwimDodge); + else + aiNewState(actor, &beastDodge); + } + break; + default: + if (!pXSector || !pXSector->Underwater) + aiNewState(actor, &beastStomp); + break; + } + } + } + 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, &beastSwimSlash); + else + aiNewState(actor, &beastSlash); + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type) + { + if (pXSector && pXSector->Underwater) + aiNewState(actor, &beastSwimSlash); + else + aiNewState(actor, &beastSlash); + } + else + { + if (pXSector && pXSector->Underwater) + aiNewState(actor, &beastSwimDodge); + else + aiNewState(actor, &beastDodge); + } + break; + default: + if (pXSector && pXSector->Underwater) + aiNewState(actor, &beastSwimSlash); + else + aiNewState(actor, &beastSlash); + 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, &beastSwimGoto); - else - aiNewState(actor, &beastGoto); - 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, &beastSwimGoto); + else + aiNewState(actor, &beastGoto); + actor->SetTarget(nullptr); } static void beastThinkSwimGoto(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, &beastSwimSearch); - 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, &beastSwimSearch); + aiThinkTarget(actor); } static void beastThinkSwimChase(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - if (actor->GetTarget() == nullptr) - { - aiNewState(actor, &beastSwimGoto); - 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, &beastSwimSearch); - return; - } - if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) - { - aiNewState(actor, &beastSwimSearch); - 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, &beastSwimSlash); - else - { - aiPlay3DSound(actor, 9009+Random(2), AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &beast138FD0); - } - } - } - else - aiNewState(actor, &beast138FD0); - return; - } - aiNewState(actor, &beastSwimGoto); - actor->SetTarget(nullptr); + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + if (actor->GetTarget() == nullptr) + { + aiNewState(actor, &beastSwimGoto); + 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, &beastSwimSearch); + return; + } + if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0) + { + aiNewState(actor, &beastSwimSearch); + 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, &beastSwimSlash); + else + { + aiPlay3DSound(actor, 9009 + Random(2), AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &beast138FD0); + } + } + } + else + aiNewState(actor, &beast138FD0); + return; + } + aiNewState(actor, &beastSwimGoto); + actor->SetTarget(nullptr); } static void beastMoveForward(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 (abs(nAng) > 341) - return; - int dx = pXSprite->targetX-pSprite->x; - int dy = pXSprite->targetY-pSprite->y; - int nDist = approxDist(dx, dy); - if (nDist <= 0x400 && Random(64) < 32) - return; - actor->xvel() += MulScale(pDudeInfo->frontSpeed, Cos(pSprite->ang), 30); - actor->yvel() += MulScale(pDudeInfo->frontSpeed, Sin(pSprite->ang), 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; + if (abs(nAng) > 341) + return; + int dx = pXSprite->targetX - pSprite->x; + int dy = pXSprite->targetY - pSprite->y; + int nDist = approxDist(dx, dy); + if (nDist <= 0x400 && Random(64) < 32) + return; + actor->xvel() += MulScale(pDudeInfo->frontSpeed, Cos(pSprite->ang), 30); + actor->yvel() += MulScale(pDudeInfo->frontSpeed, Sin(pSprite->ang), 30); } static void sub_628A0(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_62AE0(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<<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 << 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_62D7C(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); - 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; + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + int nSprite = pSprite->index; + 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; } END_BLD_NS diff --git a/source/games/blood/src/aiboneel.cpp b/source/games/blood/src/aiboneel.cpp index 8f8b704a8..a2debbd8b 100644 --- a/source/games/blood/src/aiboneel.cpp +++ b/source/games/blood/src/aiboneel.cpp @@ -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 diff --git a/source/games/blood/src/aiburn.cpp b/source/games/blood/src/aiburn.cpp index 35ac4bf7a..5c9be4644 100644 --- a/source/games/blood/src/aiburn.cpp +++ b/source/games/blood/src/aiburn.cpp @@ -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 diff --git a/source/games/blood/src/aicaleb.cpp b/source/games/blood/src/aicaleb.cpp index 7e27639ef..b641a0864 100644 --- a/source/games/blood/src/aicaleb.cpp +++ b/source/games/blood/src/aicaleb.cpp @@ -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 diff --git a/source/games/blood/src/aicerber.cpp b/source/games/blood/src/aicerber.cpp index 17ad6f32e..81a01b34e 100644 --- a/source/games/blood/src/aicerber.cpp +++ b/source/games/blood/src/aicerber.cpp @@ -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 diff --git a/source/games/blood/src/aicult.cpp b/source/games/blood/src/aicult.cpp index dc30749ed..2eaddf2ad 100644 --- a/source/games/blood/src/aicult.cpp +++ b/source/games/blood/src/aicult.cpp @@ -30,9 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -static void cultThinkSearch(DBloodActor *); -static void cultThinkGoto(DBloodActor *); -static void cultThinkChase(DBloodActor *); +static void cultThinkSearch(DBloodActor*); +static void cultThinkGoto(DBloodActor*); +static void cultThinkChase(DBloodActor*); AISTATE cultistIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE cultistProneIdle = { kAiStateIdle, 17, -1, 0, NULL, NULL, aiThinkTarget, NULL }; @@ -75,562 +75,562 @@ AISTATE cultistSwimRecoil = { kAiStateRecoil, 5, -1, 0, NULL, NULL, NULL, &culti void TommySeqCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - int dx = CosScale16(pSprite->ang); - int dy = SinScale16(pSprite->ang); - int dz = actor->dudeSlope; - dx += Random3((5-gGameOptions.nDifficulty)*1000); - dy += Random3((5-gGameOptions.nDifficulty)*1000); - dz += Random3((5-gGameOptions.nDifficulty)*500); - actFireVector(actor, 0, 0, dx, dy, dz, kVectorBullet); - sfxPlay3DSound(actor, 4001, -1, 0); + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + int dx = CosScale16(pSprite->ang); + int dy = SinScale16(pSprite->ang); + int dz = actor->dudeSlope; + dx += Random3((5 - gGameOptions.nDifficulty) * 1000); + dy += Random3((5 - gGameOptions.nDifficulty) * 1000); + dz += Random3((5 - gGameOptions.nDifficulty) * 500); + actFireVector(actor, 0, 0, dx, dy, dz, kVectorBullet); + sfxPlay3DSound(actor, 4001, -1, 0); } void TeslaSeqCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - if (Chance(dword_138BB0[gGameOptions.nDifficulty])) - { - int dx = CosScale16(pSprite->ang); - int dy = SinScale16(pSprite->ang); - int dz = actor->dudeSlope; - dx += Random3((5-gGameOptions.nDifficulty)*1000); - dy += Random3((5-gGameOptions.nDifficulty)*1000); - dz += Random3((5-gGameOptions.nDifficulty)*500); - actFireMissile(pSprite, 0, 0, dx, dy, dz, kMissileTeslaRegular); - sfxPlay3DSound(actor, 470, -1, 0); - } + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + if (Chance(dword_138BB0[gGameOptions.nDifficulty])) + { + int dx = CosScale16(pSprite->ang); + int dy = SinScale16(pSprite->ang); + int dz = actor->dudeSlope; + dx += Random3((5 - gGameOptions.nDifficulty) * 1000); + dy += Random3((5 - gGameOptions.nDifficulty) * 1000); + dz += Random3((5 - gGameOptions.nDifficulty) * 500); + actFireMissile(pSprite, 0, 0, dx, dy, dz, kMissileTeslaRegular); + sfxPlay3DSound(actor, 470, -1, 0); + } } void ShotSeqCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - int dx = CosScale16(pSprite->ang); - int dy = SinScale16(pSprite->ang); - int dz = actor->dudeSlope; - dx += Random2((5-gGameOptions.nDifficulty)*1000-500); - dy += Random2((5-gGameOptions.nDifficulty)*1000-500); - dz += Random2((5-gGameOptions.nDifficulty)*500); - for (int i = 0; i < 8; 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, 1001, -1, 0); - else - sfxPlay3DSound(actor, 1002, -1, 0); + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + int dx = CosScale16(pSprite->ang); + int dy = SinScale16(pSprite->ang); + int dz = actor->dudeSlope; + dx += Random2((5 - gGameOptions.nDifficulty) * 1000 - 500); + dy += Random2((5 - gGameOptions.nDifficulty) * 1000 - 500); + dz += Random2((5 - gGameOptions.nDifficulty) * 500); + for (int i = 0; i < 8; 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, 1001, -1, 0); + else + sfxPlay3DSound(actor, 1002, -1, 0); } void cultThrowSeqCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - int nMissile = kThingArmedTNTStick; - if (gGameOptions.nDifficulty > 2) - nMissile = kThingArmedTNTBundle; - char v4 = Chance(0x6000); - sfxPlay3DSound(actor, 455, -1, 0); - if (!actor->ValidateTarget(__FUNCTION__)) return; - spritetype *pTarget = &actor->GetTarget()->s(); - assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); - int dx = pTarget->x - pSprite->x; - int dy = pTarget->y - pSprite->y; - int dz = pTarget->z - pSprite->z; - int nDist = approxDist(dx, dy); - int nDist2 = nDist / 540; - if (nDist > 0x1e00) - v4 = 0; - auto* pMissile = actFireThing(actor, 0, 0, dz/128-14500, nMissile, (nDist2<<23)/120); - if (v4) - pMissile->x().Impact = 1; - else + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + int nMissile = kThingArmedTNTStick; + if (gGameOptions.nDifficulty > 2) + nMissile = kThingArmedTNTBundle; + char v4 = Chance(0x6000); + sfxPlay3DSound(actor, 455, -1, 0); + if (!actor->ValidateTarget(__FUNCTION__)) return; + spritetype* pTarget = &actor->GetTarget()->s(); + assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); + int dx = pTarget->x - pSprite->x; + int dy = pTarget->y - pSprite->y; + int dz = pTarget->z - pSprite->z; + int nDist = approxDist(dx, dy); + int nDist2 = nDist / 540; + if (nDist > 0x1e00) + v4 = 0; + auto* pMissile = actFireThing(actor, 0, 0, dz / 128 - 14500, nMissile, (nDist2 << 23) / 120); + if (v4) + pMissile->x().Impact = 1; + else evPost(pMissile, 120 * (1 + Random(2)), kCmdOn); } void sub_68170(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - int nMissile = kThingArmedTNTStick; - if (gGameOptions.nDifficulty > 2) - nMissile = kThingArmedTNTBundle; - sfxPlay3DSound(actor, 455, -1, 0); - auto pMissile = actFireThing(actor, 0, 0, actor->dudeSlope - 9460, nMissile, 0x133333); + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + int nMissile = kThingArmedTNTStick; + if (gGameOptions.nDifficulty > 2) + nMissile = kThingArmedTNTBundle; + sfxPlay3DSound(actor, 455, -1, 0); + auto pMissile = actFireThing(actor, 0, 0, actor->dudeSlope - 9460, nMissile, 0x133333); evPost(pMissile, 120 * (2 + Random(2)), kCmdOn); } void sub_68230(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - int nMissile = kThingArmedTNTStick; - if (gGameOptions.nDifficulty > 2) - nMissile = kThingArmedTNTBundle; - sfxPlay3DSound(actor, 455, -1, 0); - if (!actor->ValidateTarget(__FUNCTION__)) return; - spritetype *pTarget = &actor->GetTarget()->s(); - assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); - int dx = pTarget->x - pSprite->x; - int dy = pTarget->y - pSprite->y; - int dz = pTarget->z - pSprite->z; - int nDist = approxDist(dx, dy); - int nDist2 = nDist / 540; - auto pMissile = actFireThing(actor, 0, 0, dz/128-14500, nMissile, (nDist2<<17)/120); - pMissile->x().Impact = 1; + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + int nMissile = kThingArmedTNTStick; + if (gGameOptions.nDifficulty > 2) + nMissile = kThingArmedTNTBundle; + sfxPlay3DSound(actor, 455, -1, 0); + if (!actor->ValidateTarget(__FUNCTION__)) return; + spritetype* pTarget = &actor->GetTarget()->s(); + assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); + int dx = pTarget->x - pSprite->x; + int dy = pTarget->y - pSprite->y; + int dz = pTarget->z - pSprite->z; + int nDist = approxDist(dx, dy); + int nDist2 = nDist / 540; + auto pMissile = actFireThing(actor, 0, 0, dz / 128 - 14500, nMissile, (nDist2 << 17) / 120); + pMissile->x().Impact = 1; } -static char TargetNearExplosion(spritetype *pSprite) +static char TargetNearExplosion(spritetype* pSprite) { - BloodSectIterator it(pSprite->sectnum); - while (auto actor = it.Next()) - { - if (actor->s().type == kThingArmedTNTStick || actor->s().statnum == kStatExplosion) - return 1; - } - return 0; + BloodSectIterator it(pSprite->sectnum); + while (auto actor = it.Next()) + { + if (actor->s().type == kThingArmedTNTStick || actor->s().statnum == kStatExplosion) + return 1; + } + return 0; } static void cultThinkSearch(DBloodActor* actor) { - auto pXSprite = &actor->x(); - aiChooseDirection(actor,pXSprite->goalAng); - aiLookForTarget(actor); + auto pXSprite = &actor->x(); + aiChooseDirection(actor, pXSprite->goalAng); + aiLookForTarget(actor); } static void cultThinkGoto(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 < 5120 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistSearch); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimSearch); - break; - } - } - 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 < 5120 && abs(pSprite->ang - nAngle) < pDudeInfo->periphery) + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistSearch); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimSearch); + break; + } + } + aiThinkTarget(actor); } static void cultThinkChase(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - if (actor->GetTarget() == nullptr) - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistGoto); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimGoto); - break; - } - 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 (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistSearch); - if (pSprite->type == kDudeCultistTommy) - aiPlay3DSound(actor, 4021+Random(4), AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 1021+Random(4), AI_SFX_PRIORITY_1, -1); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimSearch); - break; - } - return; - } - if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) - { - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistSearch); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimSearch); - 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()); - actor->dudeSlope = DivScale(pTarget->z-pSprite->z, nDist, 10); - switch (pSprite->type) { - case kDudeCultistTommy: - if (nDist < 0x1e00 && nDist > 0xe00 && abs(nDeltaAngle) < 85 && !TargetNearExplosion(pTarget) - && (pTarget->flags&2) && gGameOptions.nDifficulty > 2 && IsPlayerSprite(pTarget) && gPlayer[pTarget->type-kDudePlayer1].isRunning - && Chance(0x8000)) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistTThrow); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistTThrow); - break; - default: - aiNewState(actor, &cultistTThrow); - break; - } - } - else if (nDist < 0x4600 && abs(nDeltaAngle) < 28) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTProneFire); - else if (dudeIsPlayingSeq(actor, 13) && (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo)) - aiNewState(actor, &cultistTSwimFire); - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun) - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistTSwimFire); - } - else - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistDodge); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistProneDodge); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSwimDodge); - } - break; - default: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistTSwimFire); - break; - } - } - break; - case kDudeCultistShotgun: - if (nDist < 0x2c00 && nDist > 0x1400 && !TargetNearExplosion(pTarget) - && (pTarget->flags&2) && gGameOptions.nDifficulty >= 2 && IsPlayerSprite(pTarget) && !gPlayer[pTarget->type-kDudePlayer1].isRunning - && Chance(0x8000)) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistSThrow); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistSThrow); - break; - default: - aiNewState(actor, &cultistSThrow); - break; - } - } - else if (nDist < 0x3200 && abs(nDeltaAngle) < 28) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSSwimFire); - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistTommy) - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSSwimFire); - } - else - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistDodge); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistProneDodge); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSwimDodge); - } - break; - default: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSSwimFire); - break; - } - } - break; - case kDudeCultistTesla: - if (nDist < 0x1e00 && nDist > 0xe00 && !TargetNearExplosion(pTarget) - && (pTarget->flags&2) && gGameOptions.nDifficulty > 2 && IsPlayerSprite(pTarget) && gPlayer[pTarget->type-kDudePlayer1].isRunning - && Chance(0x8000)) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistTsThrow); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistTsThrow); - break; - default: - aiNewState(actor, &cultistTsThrow); - break; - } - } - else if (nDist < 0x3200 && abs(nDeltaAngle) < 28) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTsFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTsProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistTsSwimFire); - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistTommy) - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTsFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTsProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistTsSwimFire); - } - else - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistDodge); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistProneDodge); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSwimDodge); - } - break; - default: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTsFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistTsProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistTsSwimFire); - break; - } - } - break; - case kDudeCultistTNT: - if (nDist < 0x2c00 && nDist > 0x1400 && abs(nDeltaAngle) < 85 - && (pTarget->flags&2) && IsPlayerSprite(pTarget)) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistDThrow); - break; - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistDThrow); - break; - default: - aiNewState(actor, &cultistDThrow); - break; - } - } - else if (nDist < 0x1400 && abs(nDeltaAngle) < 85 - && (pTarget->flags&2) && IsPlayerSprite(pTarget)) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (pXSprite->medium != 1 && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultist139A78); - break; - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultist139A78); - break; - default: - aiNewState(actor, &cultist139A78); - break; - } - } - break; - case kDudeCultistBeast: - if (nDist < 0x1e00 && nDist > 0xe00 && !TargetNearExplosion(pTarget) - && (pTarget->flags&2) && gGameOptions.nDifficulty > 2 && IsPlayerSprite(pTarget) && gPlayer[pTarget->type-kDudePlayer1].isRunning - && Chance(0x8000)) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistSThrow); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) - aiNewState(actor, &cultistSThrow); - break; - default: - aiNewState(actor, &cultistSThrow); - break; - } - } - else if (nDist < 0x3200 && abs(nDeltaAngle) < 28) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSSwimFire); - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistTommy) - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSSwimFire); - } - else - { - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistDodge); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistProneDodge); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSwimDodge); - } - break; - default: - if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSFire); - else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) - aiNewState(actor, &cultistSProneFire); - else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) - aiNewState(actor, &cultistSSwimFire); - break; - } - } - break; - } - return; - } - } - } - switch (pXSprite->medium) - { - case kMediumNormal: - aiNewState(actor, &cultistGoto); - break; - case kMediumWater: - case kMediumGoo: - aiNewState(actor, &cultistSwimGoto); - break; - } - actor->SetTarget(nullptr); + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + if (actor->GetTarget() == nullptr) + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistGoto); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimGoto); + break; + } + 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 (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistSearch); + if (pSprite->type == kDudeCultistTommy) + aiPlay3DSound(actor, 4021 + Random(4), AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 1021 + Random(4), AI_SFX_PRIORITY_1, -1); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimSearch); + break; + } + return; + } + if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0) + { + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistSearch); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimSearch); + 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()); + actor->dudeSlope = DivScale(pTarget->z - pSprite->z, nDist, 10); + switch (pSprite->type) { + case kDudeCultistTommy: + if (nDist < 0x1e00 && nDist > 0xe00 && abs(nDeltaAngle) < 85 && !TargetNearExplosion(pTarget) + && (pTarget->flags & 2) && gGameOptions.nDifficulty > 2 && IsPlayerSprite(pTarget) && gPlayer[pTarget->type - kDudePlayer1].isRunning + && Chance(0x8000)) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistTThrow); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistTThrow); + break; + default: + aiNewState(actor, &cultistTThrow); + break; + } + } + else if (nDist < 0x4600 && abs(nDeltaAngle) < 28) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTProneFire); + else if (dudeIsPlayingSeq(actor, 13) && (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo)) + aiNewState(actor, &cultistTSwimFire); + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun) + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistTSwimFire); + } + else + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistDodge); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistProneDodge); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSwimDodge); + } + break; + default: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistTSwimFire); + break; + } + } + break; + case kDudeCultistShotgun: + if (nDist < 0x2c00 && nDist > 0x1400 && !TargetNearExplosion(pTarget) + && (pTarget->flags & 2) && gGameOptions.nDifficulty >= 2 && IsPlayerSprite(pTarget) && !gPlayer[pTarget->type - kDudePlayer1].isRunning + && Chance(0x8000)) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistSThrow); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistSThrow); + break; + default: + aiNewState(actor, &cultistSThrow); + break; + } + } + else if (nDist < 0x3200 && abs(nDeltaAngle) < 28) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSSwimFire); + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistTommy) + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSSwimFire); + } + else + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistDodge); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistProneDodge); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSwimDodge); + } + break; + default: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSSwimFire); + break; + } + } + break; + case kDudeCultistTesla: + if (nDist < 0x1e00 && nDist > 0xe00 && !TargetNearExplosion(pTarget) + && (pTarget->flags & 2) && gGameOptions.nDifficulty > 2 && IsPlayerSprite(pTarget) && gPlayer[pTarget->type - kDudePlayer1].isRunning + && Chance(0x8000)) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistTsThrow); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistTsThrow); + break; + default: + aiNewState(actor, &cultistTsThrow); + break; + } + } + else if (nDist < 0x3200 && abs(nDeltaAngle) < 28) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTsFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTsProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistTsSwimFire); + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistTommy) + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTsFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTsProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistTsSwimFire); + } + else + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistDodge); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistProneDodge); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSwimDodge); + } + break; + default: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTsFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistTsProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistTsSwimFire); + break; + } + } + break; + case kDudeCultistTNT: + if (nDist < 0x2c00 && nDist > 0x1400 && abs(nDeltaAngle) < 85 + && (pTarget->flags & 2) && IsPlayerSprite(pTarget)) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistDThrow); + break; + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistDThrow); + break; + default: + aiNewState(actor, &cultistDThrow); + break; + } + } + else if (nDist < 0x1400 && abs(nDeltaAngle) < 85 + && (pTarget->flags & 2) && IsPlayerSprite(pTarget)) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (pXSprite->medium != 1 && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultist139A78); + break; + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultist139A78); + break; + default: + aiNewState(actor, &cultist139A78); + break; + } + } + break; + case kDudeCultistBeast: + if (nDist < 0x1e00 && nDist > 0xe00 && !TargetNearExplosion(pTarget) + && (pTarget->flags & 2) && gGameOptions.nDifficulty > 2 && IsPlayerSprite(pTarget) && gPlayer[pTarget->type - kDudePlayer1].isRunning + && Chance(0x8000)) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistSThrow); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistShotgun && pXSprite->medium != kMediumWater && pXSprite->medium != kMediumGoo) + aiNewState(actor, &cultistSThrow); + break; + default: + aiNewState(actor, &cultistSThrow); + break; + } + } + else if (nDist < 0x3200 && abs(nDeltaAngle) < 28) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSSwimFire); + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeCultistTommy) + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSSwimFire); + } + else + { + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistDodge); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistProneDodge); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSwimDodge); + } + break; + default: + if (!dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSFire); + else if (dudeIsPlayingSeq(actor, 14) && pXSprite->medium == kMediumNormal) + aiNewState(actor, &cultistSProneFire); + else if (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo) + aiNewState(actor, &cultistSSwimFire); + break; + } + } + break; + } + return; + } + } + } + switch (pXSprite->medium) + { + case kMediumNormal: + aiNewState(actor, &cultistGoto); + break; + case kMediumWater: + case kMediumGoo: + aiNewState(actor, &cultistSwimGoto); + break; + } + actor->SetTarget(nullptr); } END_BLD_NS diff --git a/source/games/blood/src/aigarg.cpp b/source/games/blood/src/aigarg.cpp index a23d0bd56..ffb7da04a 100644 --- a/source/games/blood/src/aigarg.cpp +++ b/source/games/blood/src/aigarg.cpp @@ -30,18 +30,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -static void gargThinkTarget(DBloodActor *); -static void gargThinkSearch(DBloodActor *); -static void gargThinkGoto(DBloodActor *); -static void gargMoveDodgeUp(DBloodActor *); -static void gargMoveDodgeDown(DBloodActor *); -static void gargThinkChase(DBloodActor *); -static void entryFStatue(DBloodActor *); -static void entrySStatue(DBloodActor *); -static void gargMoveForward(DBloodActor *); -static void gargMoveSlow(DBloodActor *); -static void gargMoveSwoop(DBloodActor *); -static void gargMoveFly(DBloodActor *); +static void gargThinkTarget(DBloodActor*); +static void gargThinkSearch(DBloodActor*); +static void gargThinkGoto(DBloodActor*); +static void gargMoveDodgeUp(DBloodActor*); +static void gargMoveDodgeDown(DBloodActor*); +static void gargThinkChase(DBloodActor*); +static void entryFStatue(DBloodActor*); +static void entrySStatue(DBloodActor*); +static void gargMoveForward(DBloodActor*); +static void gargMoveSlow(DBloodActor*); +static void gargMoveSwoop(DBloodActor*); +static void gargMoveFly(DBloodActor*); static void playStatueBreakSnd(DBloodActor*); AISTATE gargoyleFIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, gargThinkTarget, NULL }; @@ -68,648 +68,648 @@ AISTATE gargoyleDodgeDown = { kAiStateMove, 0, -1, 120, NULL, gargMoveDodgeDown, AISTATE gargoyleFDodgeDownRight = { kAiStateMove, 0, -1, 90, NULL, gargMoveDodgeDown, NULL, &gargoyleFChase }; AISTATE gargoyleFDodgeDownLeft = { kAiStateMove, 0, -1, 90, NULL, gargMoveDodgeDown, NULL, &gargoyleFChase }; -AISTATE statueFBreakSEQ = { kAiStateOther, 5, -1, 0, entryFStatue, NULL, playStatueBreakSnd, &gargoyleFMorph2}; -AISTATE statueSBreakSEQ = { kAiStateOther, 5, -1, 0, entrySStatue, NULL, playStatueBreakSnd, &gargoyleSMorph2}; +AISTATE statueFBreakSEQ = { kAiStateOther, 5, -1, 0, entryFStatue, NULL, playStatueBreakSnd, &gargoyleFMorph2 }; +AISTATE statueSBreakSEQ = { kAiStateOther, 5, -1, 0, entrySStatue, NULL, playStatueBreakSnd, &gargoyleSMorph2 }; static void playStatueBreakSnd(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - aiPlay3DSound(actor, 313, AI_SFX_PRIORITY_1, -1); + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + aiPlay3DSound(actor, 313, AI_SFX_PRIORITY_1, -1); } void SlashFSeqCallback(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 = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2; - int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2; - int dz = height-height2; - int dx = CosScale16(pSprite->ang); - int dy = SinScale16(pSprite->ang); - actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); - int r1 = Random(50); - int r2 = Random(50); - actFireVector(actor, 0, 0, dx+r2, dy-r1, dz, kVectorGargSlash); - r1 = Random(50); - r2 = Random(50); - actFireVector(actor, 0, 0, dx-r2, dy+r1, dz, kVectorGargSlash); + 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 = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2; + int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2; + int dz = height - height2; + int dx = CosScale16(pSprite->ang); + int dy = SinScale16(pSprite->ang); + actFireVector(actor, 0, 0, dx, dy, dz, kVectorGargSlash); + int r1 = Random(50); + int r2 = Random(50); + actFireVector(actor, 0, 0, dx + r2, dy - r1, dz, kVectorGargSlash); + r1 = Random(50); + r2 = Random(50); + actFireVector(actor, 0, 0, dx - r2, dy + r1, dz, kVectorGargSlash); } void ThrowFSeqCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - actFireThing(actor, 0, 0, actor->dudeSlope-7500, kThingBone, 0xeeeee); + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + actFireThing(actor, 0, 0, actor->dudeSlope - 7500, kThingBone, 0xeeeee); } void BlastSSeqCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - wrand(); // ??? - if (!actor->ValidateTarget(__FUNCTION__)) return; - spritetype *pTarget = &actor->GetTarget()->s(); - int height = (pSprite->yrepeat*getDudeInfo(pSprite->type)->eyeHeight) << 2; - int dx = pXSprite->targetX-pSprite->x; - int dy = pXSprite->targetY-pSprite->y; - int x = pSprite->x; - int y = pSprite->y; - int z = height; - TARGETTRACK tt = { 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 (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; - 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) <= 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); - if (tz > -0x333) - aim.dz = DivScale(tz, nDist, 10); - else if (tz < -0x333 && tz > -0xb33) - aim.dz = DivScale(tz, nDist, 10)+9460; - else if (tz < -0xb33 && tz > -0x3000) - aim.dz = DivScale(tz, nDist, 10)+9460; - else if (tz < -0x3000) - aim.dz = DivScale(tz, nDist, 10)-7500; - else - aim.dz = DivScale(tz, nDist, 10); - } - else - aim.dz = DivScale(tz, nDist, 10); - } - } - } - #ifdef NOONE_EXTENSIONS - // allow to fire missile in non-player targets - if (IsPlayerSprite(pTarget) || gModernMap) { - actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); - actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); - } - #else - if (IsPlayerSprite(pTarget)) { - actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); - actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); - } - #endif + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + wrand(); // ??? + if (!actor->ValidateTarget(__FUNCTION__)) return; + spritetype* pTarget = &actor->GetTarget()->s(); + int height = (pSprite->yrepeat * getDudeInfo(pSprite->type)->eyeHeight) << 2; + int dx = pXSprite->targetX - pSprite->x; + int dy = pXSprite->targetY - pSprite->y; + int x = pSprite->x; + int y = pSprite->y; + int z = height; + TARGETTRACK tt = { 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 (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; + 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) <= 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); + if (tz > -0x333) + aim.dz = DivScale(tz, nDist, 10); + else if (tz < -0x333 && tz > -0xb33) + aim.dz = DivScale(tz, nDist, 10) + 9460; + else if (tz < -0xb33 && tz > -0x3000) + aim.dz = DivScale(tz, nDist, 10) + 9460; + else if (tz < -0x3000) + aim.dz = DivScale(tz, nDist, 10) - 7500; + else + aim.dz = DivScale(tz, nDist, 10); + } + else + aim.dz = DivScale(tz, nDist, 10); + } + } + } +#ifdef NOONE_EXTENSIONS + // allow to fire missile in non-player targets + if (IsPlayerSprite(pTarget) || gModernMap) { + actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); + actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); + } +#else + if (IsPlayerSprite(pTarget)) { + actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); + actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle); + } +#endif } void ThrowSSeqCallback(int, DBloodActor* actor) { - actFireThing(actor, 0, 0, actor->dudeSlope - 7500, kThingBone, Chance(0x6000) ? 0x133333 : 0x111111); + actFireThing(actor, 0, 0, actor->dudeSlope - 7500, kThingBone, Chance(0x6000) ? 0x133333 : 0x111111); } static void gargThinkTarget(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, &gargoyleTurn); - 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, &gargoyleTurn); + 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 gargThinkSearch(DBloodActor* actor) { - auto pXSprite = &actor->x(); - aiChooseDirection(actor,pXSprite->goalAng); - aiLookForTarget(actor); + auto pXSprite = &actor->x(); + aiChooseDirection(actor, pXSprite->goalAng); + aiLookForTarget(actor); } static void gargThinkGoto(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, &gargoyleFSearch); - 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, &gargoyleFSearch); + aiThinkTarget(actor); } static void gargMoveDodgeUp(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 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); + if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { + Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); + return; + } + 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() = -0x1d555; + actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); + actor->zvel() = -0x1d555; } static void gargMoveDodgeDown(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 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); + if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { + Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); + return; + } + 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 gargThinkChase(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - if (actor->GetTarget() == nullptr) - { - aiNewState(actor, &gargoyleFGoto); - 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, &gargoyleFSearch); - return; - } - if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) - { - aiNewState(actor, &gargoyleFSearch); - 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); - switch (pSprite->type) - { - case kDudeGargoyleFlesh: - if (nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - sfxPlay3DSound(actor, 1408, 0, 0); - aiNewState(actor, &gargoyleFThrow); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleStone) - { - sfxPlay3DSound(actor, 1408, 0, 0); - aiNewState(actor, &gargoyleFThrow); - } - break; - default: - sfxPlay3DSound(actor, 1408, 0, 0); - aiNewState(actor, &gargoyleFThrow); - break; - } - } - else if (nDist < 0x400 && abs(nDeltaAngle) < 85) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - sfxPlay3DSound(actor, 1406, 0, 0); - aiNewState(actor, &gargoyleFSlash); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleStone) - { - sfxPlay3DSound(actor, 1406, 0, 0); - aiNewState(actor, &gargoyleFSlash); - } - break; - default: - sfxPlay3DSound(actor, 1406, 0, 0); - aiNewState(actor, &gargoyleFSlash); - break; - } - } - else if ((height2-height > 0x2000 || floorZ-bottom > 0x2000) && nDist < 0x1400 && nDist > 0xa00) - { - aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &gargoyleSwoop); - } - else if ((height2-height < 0x2000 || floorZ-bottom < 0x2000) && abs(nDeltaAngle) < 85) - aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); - break; - case kDudeGargoyleStone: - if (nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) - { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - sfxPlay3DSound(actor, 1457, 0, 0); - aiNewState(actor, &gargoyleSBlast); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleFlesh) - { - sfxPlay3DSound(actor, 1457, 0, 0); - aiNewState(actor, &gargoyleSBlast); - } - break; - default: - sfxPlay3DSound(actor, 1457, 0, 0); - aiNewState(actor, &gargoyleSBlast); - 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, &gargoyleFSlash); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleFlesh) - aiNewState(actor, &gargoyleFSlash); - break; - default: - aiNewState(actor, &gargoyleFSlash); - break; - } - } - else if ((height2-height > 0x2000 || floorZ-bottom > 0x2000) && nDist < 0x1400 && nDist > 0x800) - { - if (pSprite->type == kDudeGargoyleFlesh) - aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); - else - aiPlay3DSound(actor, 1450, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &gargoyleSwoop); - } - else if ((height2-height < 0x2000 || floorZ-bottom < 0x2000) && abs(nDeltaAngle) < 85) - aiPlay3DSound(actor, 1450, AI_SFX_PRIORITY_1, -1); - break; - } - } - return; - } - else - { - aiNewState(actor, &gargoyleFly); - return; - } - } + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + if (actor->GetTarget() == nullptr) + { + aiNewState(actor, &gargoyleFGoto); + 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, &gargoyleFSearch); + return; + } + if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0) + { + aiNewState(actor, &gargoyleFSearch); + 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); + switch (pSprite->type) + { + case kDudeGargoyleFlesh: + if (nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + sfxPlay3DSound(actor, 1408, 0, 0); + aiNewState(actor, &gargoyleFThrow); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleStone) + { + sfxPlay3DSound(actor, 1408, 0, 0); + aiNewState(actor, &gargoyleFThrow); + } + break; + default: + sfxPlay3DSound(actor, 1408, 0, 0); + aiNewState(actor, &gargoyleFThrow); + break; + } + } + else if (nDist < 0x400 && abs(nDeltaAngle) < 85) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + sfxPlay3DSound(actor, 1406, 0, 0); + aiNewState(actor, &gargoyleFSlash); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleStone) + { + sfxPlay3DSound(actor, 1406, 0, 0); + aiNewState(actor, &gargoyleFSlash); + } + break; + default: + sfxPlay3DSound(actor, 1406, 0, 0); + aiNewState(actor, &gargoyleFSlash); + break; + } + } + else if ((height2 - height > 0x2000 || floorZ - bottom > 0x2000) && nDist < 0x1400 && nDist > 0xa00) + { + aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &gargoyleSwoop); + } + else if ((height2 - height < 0x2000 || floorZ - bottom < 0x2000) && abs(nDeltaAngle) < 85) + aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); + break; + case kDudeGargoyleStone: + if (nDist < 0x1800 && nDist > 0xc00 && abs(nDeltaAngle) < 85) + { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + sfxPlay3DSound(actor, 1457, 0, 0); + aiNewState(actor, &gargoyleSBlast); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleFlesh) + { + sfxPlay3DSound(actor, 1457, 0, 0); + aiNewState(actor, &gargoyleSBlast); + } + break; + default: + sfxPlay3DSound(actor, 1457, 0, 0); + aiNewState(actor, &gargoyleSBlast); + 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, &gargoyleFSlash); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudeGargoyleFlesh) + aiNewState(actor, &gargoyleFSlash); + break; + default: + aiNewState(actor, &gargoyleFSlash); + break; + } + } + else if ((height2 - height > 0x2000 || floorZ - bottom > 0x2000) && nDist < 0x1400 && nDist > 0x800) + { + if (pSprite->type == kDudeGargoyleFlesh) + aiPlay3DSound(actor, 1400, AI_SFX_PRIORITY_1, -1); + else + aiPlay3DSound(actor, 1450, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &gargoyleSwoop); + } + else if ((height2 - height < 0x2000 || floorZ - bottom < 0x2000) && abs(nDeltaAngle) < 85) + aiPlay3DSound(actor, 1450, AI_SFX_PRIORITY_1, -1); + break; + } + } + return; + } + else + { + aiNewState(actor, &gargoyleFly); + return; + } + } - aiNewState(actor, &gargoyleFGoto); - actor->SetTarget(nullptr); + aiNewState(actor, &gargoyleFGoto); + actor->SetTarget(nullptr); } static void entryFStatue(DBloodActor* actor) { - auto pSprite = &actor->s(); - DUDEINFO *pDudeInfo = &dudeInfo[6]; - actHealDude(actor, pDudeInfo->startHealth, pDudeInfo->startHealth); - pSprite->type = kDudeGargoyleFlesh; + auto pSprite = &actor->s(); + DUDEINFO* pDudeInfo = &dudeInfo[6]; + actHealDude(actor, pDudeInfo->startHealth, pDudeInfo->startHealth); + pSprite->type = kDudeGargoyleFlesh; } static void entrySStatue(DBloodActor* actor) { - auto pSprite = &actor->s(); - DUDEINFO *pDudeInfo = &dudeInfo[7]; - actHealDude(actor, pDudeInfo->startHealth, pDudeInfo->startHealth); - pSprite->type = kDudeGargoyleStone; + auto pSprite = &actor->s(); + DUDEINFO* pDudeInfo = &dudeInfo[7]; + actHealDude(actor, pDudeInfo->startHealth, pDudeInfo->startHealth); + pSprite->type = kDudeGargoyleStone; } static void gargMoveForward(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 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 <= 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>>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); + if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { + Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); + return; + } + 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 <= 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 >> 1; + actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); } static void gargMoveSlow(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 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 <= 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; - t2 >>= 1; - actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); - actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); - switch (pSprite->type) { - case kDudeGargoyleFlesh: - actor->zvel() = 0x44444; - break; - case kDudeGargoyleStone: - actor->zvel() = 0x35555; - 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); + 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 <= 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; + t2 >>= 1; + actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); + switch (pSprite->type) { + case kDudeGargoyleFlesh: + actor->zvel() = 0x44444; + break; + case kDudeGargoyleStone: + actor->zvel() = 0x35555; + break; + } } static void gargMoveSwoop(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 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 <= 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); - switch (pSprite->type) { - case kDudeGargoyleFlesh: - actor->zvel() = t1; - break; - case kDudeGargoyleStone: - actor->zvel() = t1; - 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); + 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 <= 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); + switch (pSprite->type) { + case kDudeGargoyleFlesh: + actor->zvel() = t1; + break; + case kDudeGargoyleStone: + actor->zvel() = t1; + break; + } } static void gargMoveFly(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 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 <= 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); - switch (pSprite->type) { - case kDudeGargoyleFlesh: - actor->zvel() = -t1; - break; - case kDudeGargoyleStone: - actor->zvel() = -t1; - 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); + 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 <= 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); + switch (pSprite->type) { + case kDudeGargoyleFlesh: + actor->zvel() = -t1; + break; + case kDudeGargoyleStone: + actor->zvel() = -t1; + break; + } } END_BLD_NS diff --git a/source/games/blood/src/aighost.cpp b/source/games/blood/src/aighost.cpp index 63138632f..12f7e2f9a 100644 --- a/source/games/blood/src/aighost.cpp +++ b/source/games/blood/src/aighost.cpp @@ -30,16 +30,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -static void ghostThinkTarget(DBloodActor *); -static void ghostThinkSearch(DBloodActor *); -static void ghostThinkGoto(DBloodActor *); -static void ghostMoveDodgeUp(DBloodActor *); -static void ghostMoveDodgeDown(DBloodActor *); -static void ghostThinkChase(DBloodActor *); -static void ghostMoveForward(DBloodActor *); -static void ghostMoveSlow(DBloodActor *); -static void ghostMoveSwoop(DBloodActor *); -static void ghostMoveFly(DBloodActor *); +static void ghostThinkTarget(DBloodActor*); +static void ghostThinkSearch(DBloodActor*); +static void ghostThinkGoto(DBloodActor*); +static void ghostMoveDodgeUp(DBloodActor*); +static void ghostMoveDodgeDown(DBloodActor*); +static void ghostThinkChase(DBloodActor*); +static void ghostMoveForward(DBloodActor*); +static void ghostMoveSlow(DBloodActor*); +static void ghostMoveSwoop(DBloodActor*); +static void ghostMoveFly(DBloodActor*); AISTATE ghostIdle = { kAiStateIdle, 0, -1, 0, NULL, NULL, ghostThinkTarget, NULL }; @@ -63,538 +63,538 @@ AISTATE ghostDodgeDownLeft = { kAiStateMove, 0, -1, 90, NULL, ghostMoveDodgeDown void ghostSlashSeqCallback(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 = (pSprite->yrepeat*pDudeInfo->eyeHeight)<<2; - int height2 = (pTarget->yrepeat*pDudeInfoT->eyeHeight)<<2; - int dz = height-height2; - int dx = CosScale16(pSprite->ang); - int dy = SinScale16(pSprite->ang); - sfxPlay3DSound(actor, 1406, 0, 0); - actFireVector(actor, 0, 0, dx, dy, dz, kVectorGhost); - int r1 = Random(50); - int r2 = Random(50); - actFireVector(actor, 0, 0, dx+r2, dy-r1, dz, kVectorGhost); - r1 = Random(50); - r2 = Random(50); - actFireVector(actor, 0, 0, dx-r2, dy+r1, dz, kVectorGhost); + 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 = (pSprite->yrepeat * pDudeInfo->eyeHeight) << 2; + int height2 = (pTarget->yrepeat * pDudeInfoT->eyeHeight) << 2; + int dz = height - height2; + int dx = CosScale16(pSprite->ang); + int dy = SinScale16(pSprite->ang); + sfxPlay3DSound(actor, 1406, 0, 0); + actFireVector(actor, 0, 0, dx, dy, dz, kVectorGhost); + int r1 = Random(50); + int r2 = Random(50); + actFireVector(actor, 0, 0, dx + r2, dy - r1, dz, kVectorGhost); + r1 = Random(50); + r2 = Random(50); + actFireVector(actor, 0, 0, dx - r2, dy + r1, dz, kVectorGhost); } void ghostThrowSeqCallback(int, DBloodActor* actor) { - actFireThing(actor, 0, 0, actor->dudeSlope - 7500, kThingBone, 0xeeeee); + actFireThing(actor, 0, 0, actor->dudeSlope - 7500, kThingBone, 0xeeeee); } void ghostBlastSeqCallback(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); - wrand(); // ??? - if (!actor->ValidateTarget(__FUNCTION__)) return; - spritetype *pTarget = &actor->GetTarget()->s(); - int height = (pSprite->yrepeat*getDudeInfo(pSprite->type)->eyeHeight) << 2; - int dx = pXSprite->targetX-pSprite->x; - int dy = pXSprite->targetY-pSprite->y; - int x = pSprite->x; - int y = pSprite->y; - int z = height; - TARGETTRACK tt = { 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 (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); - if (tz > -0x333) - aim.dz = DivScale(tz, nDist, 10); - else if (tz < -0x333 && tz > -0xb33) - aim.dz = DivScale(tz, nDist, 10)+9460; - else if (tz < -0xb33 && tz > -0x3000) - aim.dz = DivScale(tz, nDist, 10)+9460; - else if (tz < -0x3000) - aim.dz = DivScale(tz, nDist, 10)-7500; - else - aim.dz = DivScale(tz, nDist, 10); - } - else - aim.dz = DivScale(tz, nDist, 10); - } - } - } - #ifdef NOONE_EXTENSIONS - // allow fire missile in non-player targets if not a demo - if (IsPlayerSprite(pTarget) || gModernMap) { - sfxPlay3DSound(actor, 489, 0, 0); - actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull); - } - #else - if (IsPlayerSprite(pTarget)) { - sfxPlay3DSound(actor, 489, 0, 0); - actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull); - } - #endif + XSPRITE* pXSprite = &actor->x(); + spritetype* pSprite = &actor->s(); + wrand(); // ??? + if (!actor->ValidateTarget(__FUNCTION__)) return; + spritetype* pTarget = &actor->GetTarget()->s(); + int height = (pSprite->yrepeat * getDudeInfo(pSprite->type)->eyeHeight) << 2; + int dx = pXSprite->targetX - pSprite->x; + int dy = pXSprite->targetY - pSprite->y; + int x = pSprite->x; + int y = pSprite->y; + int z = height; + TARGETTRACK tt = { 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 (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); + if (tz > -0x333) + aim.dz = DivScale(tz, nDist, 10); + else if (tz < -0x333 && tz > -0xb33) + aim.dz = DivScale(tz, nDist, 10) + 9460; + else if (tz < -0xb33 && tz > -0x3000) + aim.dz = DivScale(tz, nDist, 10) + 9460; + else if (tz < -0x3000) + aim.dz = DivScale(tz, nDist, 10) - 7500; + else + aim.dz = DivScale(tz, nDist, 10); + } + else + aim.dz = DivScale(tz, nDist, 10); + } + } + } +#ifdef NOONE_EXTENSIONS + // allow fire missile in non-player targets if not a demo + if (IsPlayerSprite(pTarget) || gModernMap) { + sfxPlay3DSound(actor, 489, 0, 0); + actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull); + } +#else + if (IsPlayerSprite(pTarget)) { + sfxPlay3DSound(actor, 489, 0, 0); + actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull); + } +#endif } static void ghostThinkTarget(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, &ghostTurn); - 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); - return; - } - else if (nDist < pDudeInfo->hearDist) - { - pDudeExtraE->thinkTime = 0; - aiSetTarget(actor, x, y, z); - aiActivateDude(actor); - return; - } - } - } + 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, &ghostTurn); + 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); + return; + } + else if (nDist < pDudeInfo->hearDist) + { + pDudeExtraE->thinkTime = 0; + aiSetTarget(actor, x, y, z); + aiActivateDude(actor); + return; + } + } + } } static void ghostThinkSearch(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 ghostThinkGoto(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, &ghostSearch); - 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, &ghostSearch); + aiThinkTarget(actor); } static void ghostMoveDodgeUp(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - int nSprite = pSprite->index; - ///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 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(); + int nSprite = pSprite->index; + ///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 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() = -0x1d555; + actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); + actor->zvel() = -0x1d555; } static void ghostMoveDodgeDown(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - int nSprite = pSprite->index; - ///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 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(); + int nSprite = pSprite->index; + ///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 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 ghostThinkChase(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - if (actor->GetTarget() == nullptr) - { - aiNewState(actor, &ghostGoto); - 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, &ghostSearch); - return; - } - if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type-kDudePlayer1], kPwUpShadowCloak) > 0) - { - aiNewState(actor, &ghostSearch); - 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); - switch (pSprite->type) { - case kDudePhantasm: - if (nDist < 0x2000 && nDist > 0x1000 && abs(nDeltaAngle) < 85) { - int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); - switch (hit) - { - case -1: - aiNewState(actor, &ghostBlast); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudePhantasm) - aiNewState(actor, &ghostBlast); - break; - default: - aiNewState(actor, &ghostBlast); - 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, &ghostSlash); - break; - case 0: - case 4: - break; - case 3: - if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudePhantasm) - aiNewState(actor, &ghostSlash); - break; - default: - aiNewState(actor, &ghostSlash); - break; - } - } - else if ((height2-height > 0x2000 || floorZ-bottom > 0x2000) && nDist < 0x1400 && nDist > 0x800) - { - aiPlay3DSound(actor, 1600, AI_SFX_PRIORITY_1, -1); - aiNewState(actor, &ghostSwoop); - } - else if ((height2-height < 0x2000 || floorZ-bottom < 0x2000) && abs(nDeltaAngle) < 85) - aiPlay3DSound(actor, 1600, AI_SFX_PRIORITY_1, -1); - break; - } - } - return; - } - else - { - aiNewState(actor, &ghostFly); - return; - } - } + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + if (actor->GetTarget() == nullptr) + { + aiNewState(actor, &ghostGoto); + 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, &ghostSearch); + return; + } + if (IsPlayerSprite(pTarget) && powerupCheck(&gPlayer[pTarget->type - kDudePlayer1], kPwUpShadowCloak) > 0) + { + aiNewState(actor, &ghostSearch); + 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); + switch (pSprite->type) { + case kDudePhantasm: + if (nDist < 0x2000 && nDist > 0x1000 && abs(nDeltaAngle) < 85) { + int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); + switch (hit) + { + case -1: + aiNewState(actor, &ghostBlast); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudePhantasm) + aiNewState(actor, &ghostBlast); + break; + default: + aiNewState(actor, &ghostBlast); + 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, &ghostSlash); + break; + case 0: + case 4: + break; + case 3: + if (pSprite->type != gHitInfo.hitactor->s().type && gHitInfo.hitactor->s().type != kDudePhantasm) + aiNewState(actor, &ghostSlash); + break; + default: + aiNewState(actor, &ghostSlash); + break; + } + } + else if ((height2 - height > 0x2000 || floorZ - bottom > 0x2000) && nDist < 0x1400 && nDist > 0x800) + { + aiPlay3DSound(actor, 1600, AI_SFX_PRIORITY_1, -1); + aiNewState(actor, &ghostSwoop); + } + else if ((height2 - height < 0x2000 || floorZ - bottom < 0x2000) && abs(nDeltaAngle) < 85) + aiPlay3DSound(actor, 1600, AI_SFX_PRIORITY_1, -1); + break; + } + } + return; + } + else + { + aiNewState(actor, &ghostFly); + return; + } + } - aiNewState(actor, &ghostGoto); - actor->SetTarget(nullptr); + aiNewState(actor, &ghostGoto); + actor->SetTarget(nullptr); } static void ghostMoveForward(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 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 <= 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>>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); + if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { + Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); + return; + } + 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 <= 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 >> 1; + actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); } static void ghostMoveSlow(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 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 <= 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; - t2 >>= 1; - actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); - actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); - switch (pSprite->type) { - case kDudePhantasm: - actor->zvel() = 0x44444; - 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); + 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 <= 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; + t2 >>= 1; + actor->xvel() = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel() = DMulScale(t1, nSin, -t2, nCos, 30); + switch (pSprite->type) { + case kDudePhantasm: + actor->zvel() = 0x44444; + break; + } } static void ghostMoveSwoop(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 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 <= 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); - switch (pSprite->type) { - case kDudePhantasm: - actor->zvel() = t1; - 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); + 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 <= 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); + switch (pSprite->type) { + case kDudePhantasm: + actor->zvel() = t1; + break; + } } static void ghostMoveFly(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 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 <= 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); - switch (pSprite->type) { - case kDudePhantasm: - actor->zvel() = -t1; - 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); + 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 <= 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); + switch (pSprite->type) { + case kDudePhantasm: + actor->zvel() = -t1; + break; + } } END_BLD_NS diff --git a/source/games/blood/src/aigilbst.cpp b/source/games/blood/src/aigilbst.cpp index 6d70d18a5..2b25d15e1 100644 --- a/source/games/blood/src/aigilbst.cpp +++ b/source/games/blood/src/aigilbst.cpp @@ -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 diff --git a/source/games/blood/src/aihand.cpp b/source/games/blood/src/aihand.cpp index ff4971185..bc8f372d9 100644 --- a/source/games/blood/src/aihand.cpp +++ b/source/games/blood/src/aihand.cpp @@ -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 diff --git a/source/games/blood/src/aihound.cpp b/source/games/blood/src/aihound.cpp index b833fc078..4765144f4 100644 --- a/source/games/blood/src/aihound.cpp +++ b/source/games/blood/src/aihound.cpp @@ -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 diff --git a/source/games/blood/src/aiinnoc.cpp b/source/games/blood/src/aiinnoc.cpp index e625ee15d..8e1491b8f 100644 --- a/source/games/blood/src/aiinnoc.cpp +++ b/source/games/blood/src/aiinnoc.cpp @@ -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); } diff --git a/source/games/blood/src/aipod.cpp b/source/games/blood/src/aipod.cpp index 684a01e38..d74aca90e 100644 --- a/source/games/blood/src/aipod.cpp +++ b/source/games/blood/src/aipod.cpp @@ -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 diff --git a/source/games/blood/src/airat.cpp b/source/games/blood/src/airat.cpp index 4799b550d..3e3bc72e1 100644 --- a/source/games/blood/src/airat.cpp +++ b/source/games/blood/src/airat.cpp @@ -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 diff --git a/source/games/blood/src/aispid.cpp b/source/games/blood/src/aispid.cpp index 87cb8fc8b..f7416c408 100644 --- a/source/games/blood/src/aispid.cpp +++ b/source/games/blood/src/aispid.cpp @@ -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 diff --git a/source/games/blood/src/aitchern.cpp b/source/games/blood/src/aitchern.cpp index 638c02cc2..51325efcf 100644 --- a/source/games/blood/src/aitchern.cpp +++ b/source/games/blood/src/aitchern.cpp @@ -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 diff --git a/source/games/blood/src/aizomba.cpp b/source/games/blood/src/aizomba.cpp index d44bd6995..84bc81042 100644 --- a/source/games/blood/src/aizomba.cpp +++ b/source/games/blood/src/aizomba.cpp @@ -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 diff --git a/source/games/blood/src/aizombf.cpp b/source/games/blood/src/aizombf.cpp index f0d06aa92..af6150c22 100644 --- a/source/games/blood/src/aizombf.cpp +++ b/source/games/blood/src/aizombf.cpp @@ -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