From ec767cb6ceb6e707b4e9f8684fb676b1e15cc42b Mon Sep 17 00:00:00 2001 From: escape209 Date: Fri, 4 Oct 2024 14:00:45 +0100 Subject: [PATCH] zNPC stuff (#382) --- src/SB/Core/x/xBehaveMgr.h | 2 + src/SB/Game/zNPCGoalRobo.cpp | 185 ++++++++++++++++++++++++++++++++ src/SB/Game/zNPCGoalStd.h | 15 ++- src/SB/Game/zNPCMessenger.h | 2 + src/SB/Game/zNPCMgr.cpp | 96 +++++++++++++++-- src/SB/Game/zNPCMgr.h | 4 + src/SB/Game/zNPCTypeBoss.h | 1 + src/SB/Game/zNPCTypeCommon.h | 1 + src/SB/Game/zNPCTypeDuplotron.h | 3 +- src/SB/Game/zNPCTypeRobot.h | 3 +- src/SB/Game/zNPCTypeSubBoss.h | 1 + src/SB/Game/zNPCTypeVillager.h | 3 + 12 files changed, 303 insertions(+), 13 deletions(-) diff --git a/src/SB/Core/x/xBehaveMgr.h b/src/SB/Core/x/xBehaveMgr.h index 1c55c4f9..934bbd0e 100644 --- a/src/SB/Core/x/xBehaveMgr.h +++ b/src/SB/Core/x/xBehaveMgr.h @@ -26,6 +26,8 @@ struct xBehaveMgr : RyzMemData void operator delete(void*, U16); }; +void xBehaveMgr_ScenePrepare(); +void xBehaveMgr_SceneReset(); void xBehaveMgr_Startup(); void xBehaveMgr_Shutdown(); xBehaveMgr* xBehaveMgr_GetSelf(); diff --git a/src/SB/Game/zNPCGoalRobo.cpp b/src/SB/Game/zNPCGoalRobo.cpp index cb4970ff..94b744d7 100644 --- a/src/SB/Game/zNPCGoalRobo.cpp +++ b/src/SB/Game/zNPCGoalRobo.cpp @@ -235,6 +235,123 @@ void zNPCGoalTubeLasso::ChkPrelimTran(en_trantype* trantype, int* nextgoal) } } +S32 zNPCGoalPatThrow::Enter(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot *)(psyche->clt_owner); + NPCGlyph* glyph = npc->glyf_stun; + if (glyph != NULL) + { + glyph->Discard(); + } + npc->glyf_stun = NULL; + zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalTubeAttack::LaserRender() +{ + zNPCTubeSlave::laser.Render(&paul.pos_laserSource, &paul.pos_laserTarget); +} + +void zNPCGoalTubeAttack::MaryzFury() +{ + zNPCTubelet* npc = *(zNPCTubelet **)(&psyche->clt_owner); + NPCHazard* haz = HAZ_Acquire(); + if (haz != NULL) + { + haz->ConfigHelper(NPC_HAZ_TUBELETBLAST); + haz->SetNPCOwner(npc); + xVec3* center = xEntGetCenter(npc); + haz->Start(center, -1.0f); + U32 sndID = xStrHash("Tube_pop"); + xSndPlay3D(sndID, 0.77f, 0.0f, 0x80, 0, &haz->pos_hazard, 5.0f, 15.0f, SND_CAT_GAME, 0.0f); + } +} + +S32 zNPCGoalStunned::Enter(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot *)(psyche->clt_owner); + if (!(flg_info & 0x10)) + { + F32 stun = npc->cfg_npc->tym_stun; + npc->tmr_stunned = (stun * (0.25f * (xurand() - 0.5f)) + stun); + } + flg_info = 0; + npc->VelStop(); + zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalTubeLasso::Exit(F32 dt, void* updCtxt) +{ + zNPCTubeSlave* npc = ((zNPCTubeSlave*)(psyche->clt_owner)); + + zNPCGoalTubeDying* tubedie = (zNPCGoalTubeDying*)psyche->FindGoal(0x4e475255); + tubedie->DeathByLasso(npc->Pos()); + + xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalDeflate::Exit(F32 dt, void* updCtxt) +{ + zNPCTubelet* npc = ((zNPCTubelet*)(psyche->clt_owner)); + xModelInstance* mdl_wig = npc->ModelAtomicShow(4, NULL); + + mdl_wig->Scale.assign(1.0f); + npc->RestoreColFlags(); + + xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalTubeDying::Exit(F32 dt, void* updCtxt) +{ + zNPCTubeSlave* npc = ((zNPCTubeSlave*)(psyche->clt_owner)); + xModelInstance* mdl_wig = npc->ModelAtomicFind(4, -1, NULL); + + mdl_wig->Scale.assign(1.0f); + npc->RestoreColFlags(); + + xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalTeleport::Exit(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = ((zNPCSleepy*)(psyche->clt_owner)); + + npc->flg_move |= 2; + npc->flg_move &= 0xFFFFFFFB; + + npc->RestoreColFlags(); + + xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalTubeBonked::Exit(F32 dt, void* updCtxt) +{ + zNPCSleepy* npc = ((zNPCSleepy*)(psyche->clt_owner)); + npc->ModelAtomicShow(0, NULL); + npc->ModelAtomicHide(1, NULL); + npc->ModelAtomicHide(4, NULL); + npc->ShowerConfetti(NULL); + npc->SndPlayRandom(NPC_STYP_UNBONKED); + xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalAlertGlove::Exit(F32 dt, void* updCtxt) +{ + zNPCGlove* npc = ((zNPCGlove*)(psyche->clt_owner)); + npc->flg_vuln |= 0x00100000; + npc->flg_vuln |= 0x82010000; + zNPC_SNDStop(eNPCSnd_GloveAttack); + xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalAlertSleepy::Exit(F32 dt, void* updCtxt) +{ + zNPCSleepy* npc = ((zNPCSleepy*)(psyche->clt_owner)); + npc->ModelAtomicHide(1, NULL); + zNPC_SNDStop(eNPCSnd_SleepyAttack); + xGoal::Exit(dt, updCtxt); +} + void zNPCGoalTubePal::ChkPrelimTran(en_trantype* trantype, int* nextgoal) { zNPCTubeSlave* npc = ((zNPCTubeSlave*)(psyche->clt_owner)); @@ -1025,6 +1142,23 @@ S32 NPCArena::IncludesPlayer(F32 rad_thresh, xVec3* vec) return 0; } +NPCGlyph* GLYF_Acquire(en_npcglyph); + +F32 zNPCGoalEvilPat::GlyphStart() +{ + static xVec3 ang_delta = { DEG2RAD(2.1f), 0.0f, 0.0f }; + static xVec3 scale = { 0.75f, 0.75f, 0.75f }; + + zNPCRobot* robot = (zNPCRobot*)psyche->clt_owner; + robot->glyf_stun = GLYF_Acquire(NPC_GLYPH_DAZED); + if (robot->glyf_stun != NULL) + { + robot->glyf_stun->Enable(1); + robot->glyf_stun->RotSet(&ang_delta, 0); + robot->glyf_stun->ScaleSet(&scale); + } +} + S32 NPCArena::IsReady() { return rad_arena > 1.0f; @@ -1482,12 +1616,63 @@ S32 zNPCGoalKnock::Exit(F32 dt, void* updCtxt) return xGoal::Exit(dt, updCtxt); } +void zNPCGoalTubeBonked::CheckForTran(en_trantype* trantype, int* nextgoal) +{ + zNPCTubeSlave* npc = (zNPCTubeSlave *)(psyche->clt_owner); + + switch (npc->tub_pete->tubestat) + { + case TUBE_STAT_BORN: + if (npc->hitpoints != 0) + { + *nextgoal = NPC_GOAL_TUBEBIRTH; + *trantype = GOAL_TRAN_SET; + } + break; + case TUBE_STAT_DUCKLING: + if (npc->hitpoints != 0) + { + *nextgoal = NPC_GOAL_TUBEDUCKLING; + *trantype = GOAL_TRAN_SET; + } + break; + case TUBE_STAT_ATTACK: + if (npc->hitpoints != 0) + { + *nextgoal = NPC_GOAL_TUBEATTACK; + *trantype = GOAL_TRAN_SET; + } + break; + case TUBE_STAT_LASSO: + *nextgoal = NPC_GOAL_TUBELASSO; + *trantype = GOAL_TRAN_SET; + break; + case TUBE_STAT_DYING: + case TUBE_STAT_DEAD: + *nextgoal = NPC_GOAL_TUBEDYING; + *trantype = GOAL_TRAN_SET; + break; + } +} + S32 zNPCGoalAlertHammer::Exit(F32 dt, void* updCtxt) { zNPCHammer* npc = ((zNPCHammer*)(psyche->clt_owner)); return xGoal::Exit(dt, updCtxt); } +S32 zNPCGoalAlert::Exit(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = ((zNPCRobot*)(psyche->clt_owner)); + if (npc->inf_battle != NULL) + { + npc->inf_battle->LeaveBattle(npc); + } + npc->inf_battle = NULL; + flg_user = 1; + return xGoal::Exit(dt, updCtxt); +} + S32 zNPCGoalLassoBase::Exit(F32 dt, void* updCtxt) { zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); diff --git a/src/SB/Game/zNPCGoalStd.h b/src/SB/Game/zNPCGoalStd.h index 7aa9dd72..fe875f05 100644 --- a/src/SB/Game/zNPCGoalStd.h +++ b/src/SB/Game/zNPCGoalStd.h @@ -556,6 +556,8 @@ class zNPCGoalAlertSleepy : public zNPCGoalCommon S32 flg_attack; // offset 0x58, size 0x4 en_slepatak sleepattack; // offset 0x5C, size 0x4 F32 tmr_minAttack; // offset 0x60, size 0x4 + + S32 Exit(F32, void*); }; class zNPCGoalChase : public zNPCGoalCommon @@ -711,6 +713,7 @@ class zNPCGoalAlertGlove : public zNPCGoalCommon } S32 Suspend(F32 dt, void* updCtxt); S32 Resume(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); F32 tmr_attack; // offset 0x4C, size 0x4 F32 tmr_minAttack; // offset 0x50, size 0x4 xVec3 pos_began; // offset 0x54, size 0xC @@ -909,7 +912,7 @@ class zNPCGoalAlert : public zNPCGoalCommon xGoal::AddFlags(0x20000); flg_npcgauto &= 0xfffffff9; } - + S32 Exit(F32 dt, void* updCtxt); S32 flg_alert; // offset 0x4C, size 0x4 }; @@ -1046,6 +1049,7 @@ class zNPCGoalTubeLasso : public zNPCGoalCommon } S32 Enter(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); void ChkPrelimTran(en_trantype* trantype, int* nextgoal); }; @@ -1071,6 +1075,7 @@ class zNPCGoalTubeDying : public zNPCGoalCommon } S32 DeathByLasso(const xVec3*); + S32 Exit(F32 dt, void* updCtxt); S32 flg_tubedying; // offset 0x4C, size 0x4 F32 spd_gothatway; // offset 0x50, size 0x4 S32 cnt_loop; // offset 0x54, size 0x4 @@ -1091,6 +1096,9 @@ class zNPCGoalTubeBonked : public zNPCGoalCommon F32 tmr_recover; // offset 0x4C, size 0x4 F32 ang_spinrate; // offset 0x50, size 0x4 xVec3 vec_offsetPete; // offset 0x54, size 0xC + + S32 Exit(F32 dt, void* updCtxt); + void CheckForTran(en_trantype*, int*); }; class zNPCGoalTubeBirth : public zNPCGoalCommon @@ -1118,8 +1126,10 @@ class zNPCGoalTubeAttack : public zNPCGoalCommon void AttackDataReset(); S32 Enter(F32 dt, void* updCtxt); S32 Resume(F32 dt, void* updCtxt); + bool MarySpinUp(float); S32 LaserRender(); void MaryzBlessing(); + void MaryzFury(); S32 MarySpinDown(F32 dt); void ChkPrelimTran(en_trantype* trantype, int* nextgoal); S32 flg_attack; // offset 0x4C, size 0x4 @@ -1189,6 +1199,8 @@ class zNPCGoalDeflate : public zNPCGoalCommon SetFlags(2); } + S32 Exit(F32 dt, void* updCtxt); + F32 spd_gothatway; // offset 0x4C, size 0x4 S32 cnt_loop; // offset 0x50, size 0x4 F32 scl_shrink; // offset 0x54, size 0x4 @@ -1268,6 +1280,7 @@ class zNPCGoalTeleport : public zNPCGoalCommon } S32 NPCMessage(NPCMsg* msg); + S32 Exit(F32 dt, void* updCtxt); F32 tmr_countdown; // offset 0x4C, size 0x4 }; diff --git a/src/SB/Game/zNPCMessenger.h b/src/SB/Game/zNPCMessenger.h index 0a099d7c..42a8e84a 100644 --- a/src/SB/Game/zNPCMessenger.h +++ b/src/SB/Game/zNPCMessenger.h @@ -4,6 +4,8 @@ #include "zNPCTypeCommon.h" #include "zNPCTypes.h" +void zNPCMsg_SceneReset(); +void zNPCMsg_ScenePrepare(); void zNPCMsg_Startup(); void zNPCMsg_Shutdown(); void zNPCMsg_AreaNotify(zNPCCommon* sender, en_NPC_MSG_ID msgid, F32 rad, S32 filter, diff --git a/src/SB/Game/zNPCMgr.cpp b/src/SB/Game/zNPCMgr.cpp index 75454687..8b784f82 100644 --- a/src/SB/Game/zNPCMgr.cpp +++ b/src/SB/Game/zNPCMgr.cpp @@ -1,14 +1,38 @@ #include "zNPCMgr.h" #include "zNPCTypeCommon.h" +#include "zNPCTypeRobot.h" +#include "zNPCTypeVillager.h" +#include "zNPCTypeSubBoss.h" +#include "zNPCTypeBoss.h" +#include "zNPCTypeDuplotron.h" #include "zNPCTypes.h" #include "zNPCSpawner.h" #include "zNPCMessenger.h" +#include "zGlobals.h" + +#include "xBehaveMgr.h" #include extern S32 g_modinit; extern zNPCMgr* g_npcmgr; +S32 g_firstFrameUpdateAllNPC; + +struct NPCMTypeTable +{ + en_NPCTYPES useNPCType; + char* modelName; + unsigned int hashOfName; +} g_tbltype[250]; + +struct NPCBrainTableEntry +{ + char* name; + en_NPCTYPES type; + unsigned int id; +} g_brainTable[63]; + zNPCMgr* zNPCMgrSelf() { return g_npcmgr; @@ -19,8 +43,14 @@ st_XORDEREDARRAY* zNPCMgr_GetNPCList() return &zNPCMgrSelf()->npclist; } -#if 0 -// Can't find the new operator declaration for some reason? +void zNPCMgr::ScenePostInit() +{ + zNPCCommon_ScenePostInit(); + zNPCRobot_ScenePostInit(); + zNPCVillager_ScenePostInit(); + zNPCDuplotron_ScenePostInit(); +} + void zNPCMgr_Startup() { if (g_modinit++ == 0) @@ -28,13 +58,10 @@ void zNPCMgr_Startup() xBehaveMgr_Startup(); zNPCMgr* npc = new (0x4e50434d, NULL) zNPCMgr(); //NPCM g_npcmgr = npc; - Startup(npc); + npc->Startup(); } } -#endif - -// Doesn't set r4 to 1 before calling the delete operator... void zNPCMgr_Shutdown() { g_modinit--; @@ -109,8 +136,59 @@ void zNPCMgr::Shutdown() zNPCMsg_Shutdown(); } -#if 0 -// Need to define all the functions. +void zNPCMgr::PrepTypeTable() +{ + for (NPCMTypeTable* p = &g_tbltype[0]; p->useNPCType != NPC_TYPE_UNKNOWN; p++) + { + p->hashOfName = xStrHash(p->modelName); + } + + for (int i = 0; i < (S32)(sizeof(g_brainTable) / sizeof(NPCBrainTableEntry)); i++) + { + g_brainTable[i].id = xStrHash(g_brainTable[i].name); + } +} + +void zNPCMgr::SceneReset() +{ + zNPCCommon_SceneReset(); + zNPCRobot_SceneReset(); + zNPCVillager_SceneReset(); + zNPCMsg_SceneReset(); + xBehaveMgr_SceneReset(); + BackdoorUpdateAllNPCsOnce(globals.sceneCur, 0.01666666f); +} + +S32 zNPCMgr_OrdTest_npcid(const void* vkey, void* vitem) +{ + S32 rc; + void* key = *(void**)(vitem); + + if (vkey < key) + { + rc = -1; + } + else if (vkey > key) + { + rc = 1; + } + else + { + rc = 0; + } + + return rc; +} + +void zNPCMgr::ScenePostSetup() +{ + for (int i = 0; i < npclist.cnt; i++) + { + xNPCBasic* npc = (xNPCBasic*)npclist.list[i]; + npc->PostSetup(); + } +} + void zNPCMgr::ScenePrepare(S32 npccnt) { XOrdInit(&this->npclist, npccnt, 0); @@ -126,8 +204,6 @@ void zNPCMgr::ScenePrepare(S32 npccnt) g_firstFrameUpdateAllNPC = 1; } -#endif - S32 zNPCMgr_OrdComp_npcid(void* vkey, void* vitem) { S32 rc; diff --git a/src/SB/Game/zNPCMgr.h b/src/SB/Game/zNPCMgr.h index 059b392b..f49dc8ad 100644 --- a/src/SB/Game/zNPCMgr.h +++ b/src/SB/Game/zNPCMgr.h @@ -14,6 +14,10 @@ struct zNPCMgr : RyzMemData xBase selfbase; zNPCMgr(); + S32 NPCTypeForModel(U32, U32); + void BackdoorUpdateAllNPCsOnce(xScene*, F32); + void PrepTypeTable(); + void Startup(); void Shutdown(); void ScenePrepare(S32 npccnt); void SceneFinish(); diff --git a/src/SB/Game/zNPCTypeBoss.h b/src/SB/Game/zNPCTypeBoss.h index 4e9e95e4..16e5cd04 100644 --- a/src/SB/Game/zNPCTypeBoss.h +++ b/src/SB/Game/zNPCTypeBoss.h @@ -25,6 +25,7 @@ struct zNPCBoss : zNPCCommon ~zNPCBoss(); }; +void zNPCBoss_ScenePrepare(); void ZNPC_Boss_Startup(); void ZNPC_Boss_Shutdown(); xFactoryInst* ZNPC_Create_Boss(S32 who, RyzMemGrow* grow, void*); diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 0af7764d..bb1e19f1 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -616,6 +616,7 @@ struct NPCMsg xFactoryInst* ZNPC_Create_Common(S32 who, RyzMemGrow* grow, void*); void ZNPC_Destroy_Common(xFactoryInst* inst); void zNPCCommon_ScenePrepare(); +void zNPCCommon_ScenePostInit(); void zNPCCommon_SceneFinish(); void zNPCPlyrSnd_Reset(); void zNPCPlyrSnd_Update(F32 dt); diff --git a/src/SB/Game/zNPCTypeDuplotron.h b/src/SB/Game/zNPCTypeDuplotron.h index f63606a9..6aa35188 100644 --- a/src/SB/Game/zNPCTypeDuplotron.h +++ b/src/SB/Game/zNPCTypeDuplotron.h @@ -30,8 +30,9 @@ struct zNPCDuplotron : zNPCCommon }; extern U32 g_hash_dupoanim[5]; - +void zNPCDuplotron_ScenePrepare(); void ZNPC_Duplotron_Startup(); +void zNPCDuplotron_ScenePostInit(); void ZNPC_Duplotron_Shutdown(); xFactoryInst* ZNPC_Create_Duplotron(S32 who, RyzMemGrow* grow, void*); void ZNPC_Destroy_Duplotron(xFactoryInst* inst); diff --git a/src/SB/Game/zNPCTypeRobot.h b/src/SB/Game/zNPCTypeRobot.h index 640c77f1..0645eae2 100644 --- a/src/SB/Game/zNPCTypeRobot.h +++ b/src/SB/Game/zNPCTypeRobot.h @@ -45,7 +45,7 @@ struct NPCLaser void ColorSet(const RwRGBA*, const RwRGBA*); U32 TextureGet(); - static void Render(xVec3&, xVec3&); + void Render(xVec3*, xVec3*); void UVScrollUpdate(F32); void Prepare(); }; @@ -547,6 +547,7 @@ struct zNPCSlick : zNPCRobot void ShieldFX(F32 dt); }; +void zNPCRobot_SceneReset(); void ZNPC_Robot_Startup(); void ZNPC_Robot_Shutdown(); void zNPCRobot_ScenePrepare(); diff --git a/src/SB/Game/zNPCTypeSubBoss.h b/src/SB/Game/zNPCTypeSubBoss.h index 3743ee16..b4664927 100644 --- a/src/SB/Game/zNPCTypeSubBoss.h +++ b/src/SB/Game/zNPCTypeSubBoss.h @@ -18,6 +18,7 @@ struct zNPCSubBoss : zNPCCommon virtual U8 PhysicsFlags() const; }; +void zNPCSubBoss_ScenePrepare(); void ZNPC_SubBoss_Startup(); void ZNPC_SubBoss_Shutdown(); void zNPCSubBoss_ScenePrepare(); diff --git a/src/SB/Game/zNPCTypeVillager.h b/src/SB/Game/zNPCTypeVillager.h index a86b76ba..223560c4 100644 --- a/src/SB/Game/zNPCTypeVillager.h +++ b/src/SB/Game/zNPCTypeVillager.h @@ -182,6 +182,9 @@ xAnimTable* ZNPC_AnimTable_BalloonBoy(xAnimTable* callerTable); xAnimTable* ZNPC_AnimTable_SuperFriend(xAnimTable* callerTable); void FOLK_KillEffects(); void FOLK_InitEffects(); +void zNPCVillager_ScenePostInit(); +void zNPCVillager_ScenePrepare(); +void zNPCVillager_SceneReset(); void ZNPC_Villager_Startup(); void ZNPC_Villager_Shutdown(); xFactoryInst* ZNPC_Create_Villager(S32 who, RyzMemGrow* growCtxt, void*);