diff --git a/source/games/exhumed/src/aistuff.h b/source/games/exhumed/src/aistuff.h index da28e6c66..3fb994e3b 100644 --- a/source/games/exhumed/src/aistuff.h +++ b/source/games/exhumed/src/aistuff.h @@ -505,6 +505,14 @@ struct AICreatureChunk : public ExhumedAI virtual void Tick(RunListEvent* ev) override; }; +struct AIMummy : public ExhumedAI +{ + void Tick(RunListEvent* ev) override; + void Damage(RunListEvent* ev) override; + void Draw(RunListEvent* ev) override; + void RadialDamage(RunListEvent* ev) override; +}; + void runlist_DispatchEvent(ExhumedAI* ai, int nObject, int nMessage, int nDamage, int nRun); diff --git a/source/games/exhumed/src/mummy.cpp b/source/games/exhumed/src/mummy.cpp index 8ad98a026..42dd8b797 100644 --- a/source/games/exhumed/src/mummy.cpp +++ b/source/games/exhumed/src/mummy.cpp @@ -173,363 +173,371 @@ void CheckMummyRevive(short nMummy) } } -void FuncMummy(int nObject, int nMessage, int nDamage, int nRun) +void AIMummy::Tick(RunListEvent* ev) { - short nMummy = RunData[nRun].nVal; + short nMummy = RunData[ev->nRun].nVal; assert(nMummy >= 0 && nMummy < kMaxMummies); short nTarget = UpdateEnemy(&MummyList[nMummy].nTarget); short nSprite = MummyList[nMummy].nSprite; - auto pSprite = &sprite[nSprite]; + auto pSprite = &sprite[nSprite]; short nAction = MummyList[nMummy].nAction; - switch (nMessage) + Gravity(nSprite); + + int nSeq = SeqOffsets[kSeqMummy] + MummySeq[nAction].a; + + pSprite->picnum = seq_GetSeqPicnum2(nSeq, MummyList[nMummy].nFrame); + + short nFrame = SeqBase[nSeq] + MummyList[nMummy].nFrame; + short nFrameFlag = FrameFlag[nFrame]; + + seq_MoveSequence(nSprite, nSeq, MummyList[nMummy].nFrame); + + bool bVal = false; + + MummyList[nMummy].nFrame++; + if (MummyList[nMummy].nFrame >= SeqSize[nSeq]) { - default: + MummyList[nMummy].nFrame = 0; + + bVal = true; + } + + if (nTarget != -1 && nAction < 4) + { + if ((!sprite[nTarget].cstat) && nAction) { - DebugOut("unknown msg %d for Mummy\n", nMessage); - break; + MummyList[nMummy].nAction = 0; + MummyList[nMummy].nFrame = 0; + pSprite->xvel = 0; + pSprite->yvel = 0; + } + } + + int nMov = MoveCreatureWithCaution(nSprite); + + if (nAction > 7) + return; + + switch (nAction) + { + case 0: + { + if ((MummyList[nMummy].nIndex & 0x1F) == (totalmoves & 0x1F)) + { + pSprite->cstat = 0x101; + + if (nTarget < 0) + { + int nTarget = FindPlayer(nSprite, 100); + if (nTarget >= 0) + { + D3PlayFX(StaticSound[kSound7], nSprite); + MummyList[nMummy].nFrame = 0; + MummyList[nMummy].nTarget = nTarget; + MummyList[nMummy].nAction = 1; + MummyList[nMummy].nCount = 90; + + pSprite->xvel = bcos(pSprite->ang, -2); + pSprite->yvel = bsin(pSprite->ang, -2); + } + } + } + return; + } + + case 1: + { + if (MummyList[nMummy].nCount > 0) + { + MummyList[nMummy].nCount--; } - case 0x20000: + if ((MummyList[nMummy].nIndex & 0x1F) == (totalmoves & 0x1F)) { - Gravity(nSprite); + pSprite->cstat = 0x101; - int nSeq = SeqOffsets[kSeqMummy] + MummySeq[nAction].a; + PlotCourseToSprite(nSprite, nTarget); - pSprite->picnum = seq_GetSeqPicnum2(nSeq, MummyList[nMummy].nFrame); - - short nFrame = SeqBase[nSeq] + MummyList[nMummy].nFrame; - short nFrameFlag = FrameFlag[nFrame]; - - seq_MoveSequence(nSprite, nSeq, MummyList[nMummy].nFrame); - - bool bVal = false; - - MummyList[nMummy].nFrame++; - if (MummyList[nMummy].nFrame >= SeqSize[nSeq]) + if (MummyList[nMummy].nAction == 1) { - MummyList[nMummy].nFrame = 0; - - bVal = true; - } - - if (nTarget != -1 && nAction < 4) - { - if ((!sprite[nTarget].cstat) && nAction) + if (RandomBit()) { - MummyList[nMummy].nAction = 0; - MummyList[nMummy].nFrame = 0; - pSprite->xvel = 0; - pSprite->yvel = 0; - } - } - - int nMov = MoveCreatureWithCaution(nSprite); - - if (nAction > 7) - return; - - switch (nAction) - { - case 0: - { - if ((MummyList[nMummy].nIndex & 0x1F) == (totalmoves & 0x1F)) + if (cansee(pSprite->x, pSprite->y, pSprite->z - GetSpriteHeight(nSprite), pSprite->sectnum, + sprite[nTarget].x, sprite[nTarget].y, sprite[nTarget].z - GetSpriteHeight(nTarget), sprite[nTarget].sectnum)) { - pSprite->cstat = 0x101; - - if (nTarget < 0) - { - int nTarget = FindPlayer(nSprite, 100); - if (nTarget >= 0) - { - D3PlayFX(StaticSound[kSound7], nSprite); - MummyList[nMummy].nFrame = 0; - MummyList[nMummy].nTarget = nTarget; - MummyList[nMummy].nAction = 1; - MummyList[nMummy].nCount = 90; - - pSprite->xvel = bcos(pSprite->ang, -2); - pSprite->yvel = bsin(pSprite->ang, -2); - } - } - } - return; - } - - case 1: - { - if (MummyList[nMummy].nCount > 0) - { - MummyList[nMummy].nCount--; - } - - if ((MummyList[nMummy].nIndex & 0x1F) == (totalmoves & 0x1F)) - { - pSprite->cstat = 0x101; - - PlotCourseToSprite(nSprite, nTarget); - - if (MummyList[nMummy].nAction == 1) - { - if (RandomBit()) - { - if (cansee(pSprite->x, pSprite->y, pSprite->z - GetSpriteHeight(nSprite), pSprite->sectnum, - sprite[nTarget].x, sprite[nTarget].y, sprite[nTarget].z - GetSpriteHeight(nTarget), sprite[nTarget].sectnum)) - { - MummyList[nMummy].nAction = 3; - MummyList[nMummy].nFrame = 0; - - pSprite->xvel = 0; - pSprite->yvel = 0; - return; - } - } - } - } - - // loc_2B5A8 - if (!MummyList[nMummy].nFrame) - { - pSprite->xvel = bcos(pSprite->ang, -1); - pSprite->yvel = bsin(pSprite->ang, -1); - } - - if (pSprite->xvel || pSprite->yvel) - { - if (pSprite->xvel > 0) - { - pSprite->xvel -= 1024; - if (pSprite->xvel < 0) { - pSprite->xvel = 0; - } - } - else if (pSprite->xvel < 0) - { - pSprite->xvel += 1024; - if (pSprite->xvel > 0) { - pSprite->xvel = 0; - } - } - - if (pSprite->yvel > 0) - { - pSprite->yvel -= 1024; - if (pSprite->yvel < 0) { - pSprite->yvel = 0; - } - } - else if (pSprite->yvel < 0) - { - pSprite->yvel += 1024; - if (pSprite->yvel > 0) { - pSprite->yvel = 0; - } - } - } - - if (nMov) - { - switch (nMov & 0xC000) - { - case 0x8000: - { - pSprite->ang = (pSprite->ang + ((RandomWord() & 0x3FF) + 1024)) & kAngleMask; - pSprite->xvel = bcos(pSprite->ang, -2); - pSprite->yvel = bsin(pSprite->ang, -2); - return; - } - - case 0xC000: - { - if ((nMov & 0x3FFF) == nTarget) - { - int nAngle = getangle(sprite[nTarget].x - pSprite->x, sprite[nTarget].y - pSprite->y); - if (AngleDiff(pSprite->ang, nAngle) < 64) - { - MummyList[nMummy].nAction = 2; - MummyList[nMummy].nFrame = 0; - - pSprite->xvel = 0; - pSprite->yvel = 0; - } - } - return; - } - } - } - - break; - } - - case 2: - { - if (nTarget == -1) - { - MummyList[nMummy].nAction = 0; + MummyList[nMummy].nAction = 3; MummyList[nMummy].nFrame = 0; - } - else - { - if (PlotCourseToSprite(nSprite, nTarget) >= 1024) - { - MummyList[nMummy].nAction = 1; - MummyList[nMummy].nFrame = 0; - } - else if (nFrameFlag & 0x80) - { - runlist_DamageEnemy(nTarget, nSprite, 5); - } - } - return; - } - case 3: - { - if (bVal) - { - MummyList[nMummy].nFrame = 0; - MummyList[nMummy].nAction = 0; - MummyList[nMummy].nCount = 100; - MummyList[nMummy].nTarget = -1; - return; - } - else if (nFrameFlag & 0x80) - { - SetQuake(nSprite, 100); - - // low 16 bits of returned var contains the sprite index, the high 16 the bullet number - int nBullet = BuildBullet(nSprite, 9, 0, 0, -15360, pSprite->ang, nTarget + 10000, 1); - CheckMummyRevive(nMummy); - - if (nBullet > -1) - { - if (!RandomSize(3)) - { - // FIXME CHECKME - nBullet & 0xFFFF can be -1. Original code doesn't handle this?? - - SetBulletEnemy(FixedToInt(nBullet), nTarget); // isolate the bullet number (shift off the sprite index) - sprite[nBullet & 0xFFFF].pal = 5; - } - } - } - return; - } - - case 4: - { - if (bVal) - { - MummyList[nMummy].nFrame = 0; - MummyList[nMummy].nAction = 5; - } - return; - } - - case 5: - { - MummyList[nMummy].nFrame = 0; - return; - } - - case 6: - { - if (bVal) - { - pSprite->cstat = 0x101; - - MummyList[nMummy].nAction = 0; - MummyList[nMummy].nHealth = 300; - MummyList[nMummy].nTarget = -1; - - nCreaturesTotal++; - } - return; - } - - case 7: - { - if (nMov & 0x20000) - { - pSprite->xvel >>= 1; - pSprite->yvel >>= 1; - } - - if (bVal) - { pSprite->xvel = 0; pSprite->yvel = 0; - pSprite->cstat = 0x101; - - MummyList[nMummy].nAction = 0; - MummyList[nMummy].nFrame = 0; - MummyList[nMummy].nTarget = -1; + return; } + } + } + } - return; + // loc_2B5A8 + if (!MummyList[nMummy].nFrame) + { + pSprite->xvel = bcos(pSprite->ang, -1); + pSprite->yvel = bsin(pSprite->ang, -1); + } + + if (pSprite->xvel || pSprite->yvel) + { + if (pSprite->xvel > 0) + { + pSprite->xvel -= 1024; + if (pSprite->xvel < 0) { + pSprite->xvel = 0; + } + } + else if (pSprite->xvel < 0) + { + pSprite->xvel += 1024; + if (pSprite->xvel > 0) { + pSprite->xvel = 0; } } - return; - } - - case 0x90000: - { - seq_PlotSequence(nObject, SeqOffsets[kSeqMummy] + MummySeq[nAction].a, MummyList[nMummy].nFrame, MummySeq[nAction].b); - return; - } - - case 0xA0000: - { - if (MummyList[nMummy].nHealth <= 0) - return; - - nDamage = runlist_CheckRadialDamage(nSprite); - // fall through to 0x80000 - fallthrough__; - } - case 0x80000: - { - if (nDamage <= 0) - return; - - if (MummyList[nMummy].nHealth <= 0) { - return; - } - - MummyList[nMummy].nHealth -= dmgAdjust(nDamage); - - if (MummyList[nMummy].nHealth <= 0) + if (pSprite->yvel > 0) { - MummyList[nMummy].nHealth = 0; - pSprite->cstat &= 0xFEFE; - nCreaturesKilled++; - - DropMagic(nSprite); - - MummyList[nMummy].nFrame = 0; - MummyList[nMummy].nAction = 4; - - pSprite->xvel = 0; - pSprite->yvel = 0; - pSprite->zvel = 0; - pSprite->z = sector[pSprite->sectnum].floorz; - } - else - { - if (!RandomSize(2)) - { - MummyList[nMummy].nAction = 7; - MummyList[nMummy].nFrame = 0; - - pSprite->xvel = 0; + pSprite->yvel -= 1024; + if (pSprite->yvel < 0) { pSprite->yvel = 0; } } + else if (pSprite->yvel < 0) + { + pSprite->yvel += 1024; + if (pSprite->yvel > 0) { + pSprite->yvel = 0; + } + } + } + if (nMov) + { + switch (nMov & 0xC000) + { + case 0x8000: + { + pSprite->ang = (pSprite->ang + ((RandomWord() & 0x3FF) + 1024)) & kAngleMask; + pSprite->xvel = bcos(pSprite->ang, -2); + pSprite->yvel = bsin(pSprite->ang, -2); + return; + } + + case 0xC000: + { + if ((nMov & 0x3FFF) == nTarget) + { + int nAngle = getangle(sprite[nTarget].x - pSprite->x, sprite[nTarget].y - pSprite->y); + if (AngleDiff(pSprite->ang, nAngle) < 64) + { + MummyList[nMummy].nAction = 2; + MummyList[nMummy].nFrame = 0; + + pSprite->xvel = 0; + pSprite->yvel = 0; + } + } + return; + } + } + } + + break; + } + + case 2: + { + if (nTarget == -1) + { + MummyList[nMummy].nAction = 0; + MummyList[nMummy].nFrame = 0; + } + else + { + if (PlotCourseToSprite(nSprite, nTarget) >= 1024) + { + MummyList[nMummy].nAction = 1; + MummyList[nMummy].nFrame = 0; + } + else if (nFrameFlag & 0x80) + { + runlist_DamageEnemy(nTarget, nSprite, 5); + } + } + return; + } + + case 3: + { + if (bVal) + { + MummyList[nMummy].nFrame = 0; + MummyList[nMummy].nAction = 0; + MummyList[nMummy].nCount = 100; + MummyList[nMummy].nTarget = -1; return; } + else if (nFrameFlag & 0x80) + { + SetQuake(nSprite, 100); + + // low 16 bits of returned var contains the sprite index, the high 16 the bullet number + int nBullet = BuildBullet(nSprite, 9, 0, 0, -15360, pSprite->ang, nTarget + 10000, 1); + CheckMummyRevive(nMummy); + + if (nBullet > -1) + { + if (!RandomSize(3)) + { + // FIXME CHECKME - nBullet & 0xFFFF can be -1. Original code doesn't handle this?? + + SetBulletEnemy(FixedToInt(nBullet), nTarget); // isolate the bullet number (shift off the sprite index) + sprite[nBullet & 0xFFFF].pal = 5; + } + } } + return; + } + + case 4: + { + if (bVal) + { + MummyList[nMummy].nFrame = 0; + MummyList[nMummy].nAction = 5; + } + return; + } + + case 5: + { + MummyList[nMummy].nFrame = 0; + return; + } + + case 6: + { + if (bVal) + { + pSprite->cstat = 0x101; + + MummyList[nMummy].nAction = 0; + MummyList[nMummy].nHealth = 300; + MummyList[nMummy].nTarget = -1; + + nCreaturesTotal++; + } + return; + } + + case 7: + { + if (nMov & 0x20000) + { + pSprite->xvel >>= 1; + pSprite->yvel >>= 1; + } + + if (bVal) + { + pSprite->xvel = 0; + pSprite->yvel = 0; + pSprite->cstat = 0x101; + + MummyList[nMummy].nAction = 0; + MummyList[nMummy].nFrame = 0; + MummyList[nMummy].nTarget = -1; + } + + return; + } + } } + +void AIMummy::Draw(RunListEvent* ev) +{ + short nMummy = RunData[ev->nRun].nVal; + assert(nMummy >= 0 && nMummy < kMaxMummies); + short nAction = MummyList[nMummy].nAction; + + seq_PlotSequence(ev->nIndex, SeqOffsets[kSeqMummy] + MummySeq[nAction].a, MummyList[nMummy].nFrame, MummySeq[nAction].b); + return; +} + +void AIMummy::RadialDamage(RunListEvent* ev) +{ + short nMummy = RunData[ev->nRun].nVal; + assert(nMummy >= 0 && nMummy < kMaxMummies); + short nSprite = MummyList[nMummy].nSprite; + auto pSprite = &sprite[nSprite]; + + if (MummyList[nMummy].nHealth <= 0) + return; + + ev->nDamage = runlist_CheckRadialDamage(nSprite); + Damage(ev); +} + +void AIMummy::Damage(RunListEvent* ev) +{ + short nMummy = RunData[ev->nRun].nVal; + assert(nMummy >= 0 && nMummy < kMaxMummies); + + short nSprite = MummyList[nMummy].nSprite; + auto pSprite = &sprite[nSprite]; + + if (ev->nDamage <= 0) + return; + + if (MummyList[nMummy].nHealth <= 0) { + return; + } + + MummyList[nMummy].nHealth -= dmgAdjust(ev->nDamage); + + if (MummyList[nMummy].nHealth <= 0) + { + MummyList[nMummy].nHealth = 0; + pSprite->cstat &= 0xFEFE; + nCreaturesKilled++; + + DropMagic(nSprite); + + MummyList[nMummy].nFrame = 0; + MummyList[nMummy].nAction = 4; + + pSprite->xvel = 0; + pSprite->yvel = 0; + pSprite->zvel = 0; + pSprite->z = sector[pSprite->sectnum].floorz; + } + else + { + if (!RandomSize(2)) + { + MummyList[nMummy].nAction = 7; + MummyList[nMummy].nFrame = 0; + + pSprite->xvel = 0; + pSprite->yvel = 0; + } + } + + return; +} + +void FuncMummy(int nObject, int nMessage, int nDamage, int nRun) +{ + AIMummy ai; + runlist_DispatchEvent(&ai, nObject, nMessage, nDamage, nRun); +} + END_PS_NS