From 089e74dbc702ec3d4059cf597dbf4a831deb726d Mon Sep 17 00:00:00 2001 From: escape209 Date: Mon, 16 Jun 2025 10:29:50 +0100 Subject: [PATCH] zNPC stuff --- src/SB/Core/x/xNPCBasic.h | 1 + src/SB/Game/zNPCGoalCommon.h | 1 + src/SB/Game/zNPCGoalRobo.cpp | 154 +++++++++++++++++++++++++++++++++ src/SB/Game/zNPCGoalStd.h | 17 +++- src/SB/Game/zNPCTypeCommon.cpp | 85 ++++++++++++++++-- src/SB/Game/zNPCTypeCommon.h | 8 +- src/SB/Game/zNPCTypeRobot.h | 2 +- 7 files changed, 257 insertions(+), 11 deletions(-) diff --git a/src/SB/Core/x/xNPCBasic.h b/src/SB/Core/x/xNPCBasic.h index 121f313bf..4d522a372 100644 --- a/src/SB/Core/x/xNPCBasic.h +++ b/src/SB/Core/x/xNPCBasic.h @@ -23,6 +23,7 @@ enum en_npcdcat eNPCDCAT_Seven = 7, eNPCDCAT_Eight = 8, eNPCDCAT_Eleven = 11, + eNPCDCAT_Thirteen = 13, }; struct xNPCBasic : xEnt, xFactoryInst diff --git a/src/SB/Game/zNPCGoalCommon.h b/src/SB/Game/zNPCGoalCommon.h index 1c1540400..b11b38f6e 100644 --- a/src/SB/Game/zNPCGoalCommon.h +++ b/src/SB/Game/zNPCGoalCommon.h @@ -22,6 +22,7 @@ struct zNPCGoalCommon : xGoal U32 DoAutoAnim(en_NPC_GOAL_SPOT gspot, S32 forceRestart); U32 DoExplicitAnim(U32 anid, S32 forceRestart); + void KickFromTheNest(); const char* Name() { diff --git a/src/SB/Game/zNPCGoalRobo.cpp b/src/SB/Game/zNPCGoalRobo.cpp index 922417c18..99cced71c 100644 --- a/src/SB/Game/zNPCGoalRobo.cpp +++ b/src/SB/Game/zNPCGoalRobo.cpp @@ -234,6 +234,26 @@ void zNPCGoalTubeLasso::ChkPrelimTran(en_trantype* trantype, int* nextgoal) } } +S32 zNPCGoalTubeLasso::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + S32 nextgoal = 0; + ChkPrelimTran(trantype, &nextgoal); + if (*trantype != GOAL_TRAN_NONE) + { + return nextgoal; + } + MoveTryToEscape(dt); + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +void zNPCGoalDogDash::HoundPlayer(F32 dt) +{ + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + npc->ThrottleAdjust(dt, 4.0f, 20.0f); + xVec3* dir = NPCC_faceDir(npc); + npc->ThrottleApply(dt, dir, 0); +} + S32 zNPCGoalPatThrow::Enter(F32 dt, void* updCtxt) { zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); @@ -246,11 +266,106 @@ S32 zNPCGoalPatThrow::Enter(F32 dt, void* updCtxt) return zNPCGoalCommon::Enter(dt, updCtxt); } +S32 zNPCGoalAlertGlove::Enter(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + CalcAttackVector(); + npc->flg_vuln &= 0xffefffff; + npc->flg_vuln &= 0x7dfeffff; + tmr_minAttack = 1.0f; + zNPC_SNDPlay3D(eNPCSnd_GloveAttack, npc); + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertSleepy::Enter(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + flg_attack = 0; + sleepattack = SLEEP_ATAK_REACT; + npc->VelStop(); + npc->ModelAtomicHide(1, NULL); + zNPC_SNDPlay3D(eNPCSnd_SleepyAttack, npc); + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAttackSlick::Enter(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + idx_launch = 1; + zNPCGoalLoopAnim::LoopCountSet(1); + npc->SndPlayRandom(NPC_STYP_ATTACK); + return zNPCGoalLoopAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalAttackChuck::Enter(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + idx_launch = 1; + npc->ModelAtomicHide(1, NULL); + npc->SndPlayRandom(NPC_STYP_WEPLAUNCH); + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalPatCarry::Enter(F32 dt, void* updCtxt) +{ + static xVec3 scale = { 0.3f, 0.3f, 0.3f }; + + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + NPCGlyph* glyph = npc->glyf_stun; + if (glyph != NULL) + { + glyph->ScaleSet(&scale); + } + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertFodBomb::Enter(F32 dt, void* updCtxt) +{ + zNPCFodBomb* npc = (zNPCFodBomb*)(psyche->clt_owner); + flg_attack = 0; + tmr_nextping = 0.0f; + alertbomb = FODBOMB_ALERT_NOTICE; + npc->BlinkerReset(); + return zNPCGoalCommon::Enter(dt, updCtxt); +} + void zNPCGoalTubeAttack::LaserRender() { zNPCTubeSlave::laser.Render(&paul.pos_laserSource, &paul.pos_laserTarget); } +S32 zNPCGoalTubeAttack::MarySpinUp(F32 dt) +{ + S32 retval = 0; + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + npc->DBG_IsNormLog(eNPCDCAT_Thirteen, -1); + if (mary.ang_spinrate > (8 * PI)) + { + retval = 1; + } + else + { + mary.ang_spinrate += (2 * PI) * dt; + } + npc->frame->drot.angle = (dt * mary.ang_spinrate); + npc->frame->mode |= 0x20; + return retval; +} + +void zNPCGoalAlertFodBomb::Detonate() +{ + zNPCFodBomb* npc = *(zNPCFodBomb**)(&psyche->clt_owner); + npc->SndPlayRandom(NPC_STYP_ATTACK); + NPCHazard* haz = HAZ_Acquire(); + if (haz != NULL) + { + haz->ConfigHelper(NPC_HAZ_FODBOMB); + haz->SetNPCOwner(npc); + xVec3* center = xEntGetCenter(npc); + haz->Start(center, -1.0f); + } +} + void zNPCGoalTubeAttack::MaryzFury() { zNPCTubelet* npc = *(zNPCTubelet**)(&psyche->clt_owner); @@ -1749,6 +1864,45 @@ void zNPCGoalKnock::StreakDone() streakID = 0xDEAD; } +S32 zNPCGoalRespawn::Enter(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + tmr_respawn = 0.35f; + cnt_ring = 0; + if (!(flg_info & 0x10)) + { + xVec3Copy(&pos_poofHere, &npc->entass->pos); + npc->GetParm(NPC_PARM_FIRSTMVPT, &((zNPCCommon*)(npc))->nav_curr); + } + xVec3Copy(npc->Pos(), &pos_poofHere); + xVec3Copy(&npc->frame->mat.pos, &pos_poofHere); + npc->frame->mode = 1; + flg_info = 0; + if (((zNPCCommon*)(npc))->npc_duplodude != 0) + { + tmr_robobits = LaunchRoboBits(); + xEntHide(npc); + } + else + { + tmr_robobits = -1.0f; + } + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalRespawn::Exit(F32 dt, void* updCtxt) +{ + zNPCRobot* npc = (zNPCRobot*)(psyche->clt_owner); + KickFromTheNest(); + xEntShow(npc); + zNPCCommon* duper = npc->npc_duplodude; + if (duper != NULL) + { + duper->DuploNotice(SM_NOTE_NPCALIVE, npc); + } + return xGoal::Exit(dt, updCtxt); +} + void zNPCGoalAttackArfMelee::FXStreakDone() { for (S32 i = 0; i < (S32)(sizeof(this->streakID) / sizeof(U32)); i++) diff --git a/src/SB/Game/zNPCGoalStd.h b/src/SB/Game/zNPCGoalStd.h index c962efb22..d3756c5ab 100644 --- a/src/SB/Game/zNPCGoalStd.h +++ b/src/SB/Game/zNPCGoalStd.h @@ -278,6 +278,7 @@ class zNPCGoalAttackChuck : public zNPCGoalPushAnim S32 BombzAway(F32); S32 Exit(F32 dt, void* updCtxt); + S32 Enter(F32 dt, void* updCtxt); S32 idx_launch; // offset 0x54, size 0x4 }; @@ -329,6 +330,7 @@ class zNPCGoalAttackSlick : public zNPCGoalLoopAnim } S32 FireOne(S32); + S32 Enter(F32 dt, void* updCtxt); S32 idx_launch; // offset 0x6C, size 0x4 }; @@ -447,6 +449,8 @@ class zNPCGoalPatCarry : public zNPCGoalCommon { xGoal::SetFlags(2); } + + S32 Enter(F32 dt, void* updCtxt); }; class zNPCGoalStunned : public zNPCGoalCommon @@ -558,6 +562,7 @@ class zNPCGoalAlertSleepy : public zNPCGoalCommon F32 tmr_minAttack; // offset 0x60, size 0x4 S32 Exit(F32, void*); + S32 Enter(F32 dt, void* updCtxt); }; class zNPCGoalChase : public zNPCGoalCommon @@ -713,7 +718,9 @@ class zNPCGoalAlertGlove : public zNPCGoalCommon } S32 Suspend(F32 dt, void* updCtxt); S32 Resume(F32 dt, void* updCtxt); + S32 Enter(F32 dt, void* updCtxt); S32 Exit(F32 dt, void* updCtxt); + void CalcAttackVector(); F32 tmr_attack; // offset 0x4C, size 0x4 F32 tmr_minAttack; // offset 0x50, size 0x4 xVec3 pos_began; // offset 0x54, size 0xC @@ -925,6 +932,8 @@ class zNPCGoalAlertFodBomb : public zNPCGoalCommon } S32 Resume(F32 dt, void* updCtxt); + S32 Enter(F32 dt, void* updCtxt); + void Detonate(); S32 flg_attack; // offset 0x4C, size 0x4 en_alertbomb alertbomb; // offset 0x50, size 0x4 F32 tmr_nextping; // offset 0x54, size 0x4 @@ -1050,6 +1059,8 @@ class zNPCGoalTubeLasso : public zNPCGoalCommon S32 Enter(F32 dt, void* updCtxt); S32 Exit(F32 dt, void* updCtxt); void ChkPrelimTran(en_trantype* trantype, int* nextgoal); + S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + void MoveTryToEscape(F32 dt); }; class zNPCGoalTubeDead : public zNPCGoalDead @@ -1123,7 +1134,7 @@ class zNPCGoalTubeAttack : public zNPCGoalCommon void AttackDataReset(); S32 Enter(F32 dt, void* updCtxt); S32 Resume(F32 dt, void* updCtxt); - bool MarySpinUp(float); + S32 MarySpinUp(F32 dt); void LaserRender(); void MaryzBlessing(); void MaryzFury(); @@ -1213,6 +1224,9 @@ class zNPCGoalRespawn : public zNPCGoalCommon } S32 InputInfo(NPCSpawnInfo* info); + S32 Enter(F32, void*); + S32 Exit(F32, void*); + F32 LaunchRoboBits(); F32 tmr_respawn; // offset 0x4C, size 0x4 F32 tmr_robobits; // offset 0x50, size 0x4 S32 cnt_ring; // offset 0x54, size 0x4 @@ -1306,6 +1320,7 @@ class zNPCGoalDogDash : public zNPCGoalLoopAnim } S32 Enter(F32 dt, void* updCtxt); + void HoundPlayer(F32 dt); }; xFactoryInst* GOALCreate_Standard(S32 who, RyzMemGrow* grow, void*); diff --git a/src/SB/Game/zNPCTypeCommon.cpp b/src/SB/Game/zNPCTypeCommon.cpp index baaa96d04..3eb5e7a37 100644 --- a/src/SB/Game/zNPCTypeCommon.cpp +++ b/src/SB/Game/zNPCTypeCommon.cpp @@ -22,7 +22,7 @@ #define LassoGuide_Hold01 2 extern char zNPCTypeCommon_strings[]; -static char* g_strz_lassanim[3] = {"Unknown", "LassoGuide_Grab01", "LassoGuide_Hold01"}; +static char* g_strz_lassanim[3] = { "Unknown", "LassoGuide_Grab01", "LassoGuide_Hold01" }; extern S32 g_hash_lassanim[3]; extern volatile S32 g_skipDescent; extern NPCConfig* g_ncfghead; @@ -104,7 +104,7 @@ void zNPCCommon_ScenePostInit() NPCSupport_ScenePostInit(); } -void zNPCCommon_Timestep(F32 dt) +void zNPCCommon_Timestep(xScene* scene, F32 dt) { NPCSupport_Timestep(dt); NPCS_SndTimersUpdate(dt); @@ -180,6 +180,16 @@ S32 zNPCCommon::GetVertPos(en_mdlvert vid, xVec3* pos) return 1; } +void zNPCPlyrSnd_Reset() +{ + g_tmr_talkless = 10.0f; +} + +void zNPCPlyrSnd_Update(F32 dt) +{ + g_tmr_talkless = MAX(-1.0f, g_tmr_talkless - dt); +} + void zNPCCommon::ConfigSceneDone() { g_ncfghead = 0; @@ -191,6 +201,64 @@ void zNPCCommon_WonderReset() g_flg_wonder = 0; } +U32 zNPCCommon::CanDoSplines() +{ + bool retval = false; + if ((npcset.useNavSplines) && ((flg_move) & 8)) + { + retval = true; + } + return retval; +} + +zMovePoint* zNPCCommon::FirstAssigned() +{ + zMovePoint* nav_first = NULL; + zNPCCommon::GetParm(NPC_PARM_FIRSTMVPT, &nav_first); + return nav_first; +} + +U32 zNPCCommon::AnimCurStateID() +{ + xAnimState* state = AnimCurState(); + if (state != NULL) + { + return state->ID; + } + else + { + return 0; + } +} + +F32 zNPCCommon::AnimDuration(xAnimState* ast) +{ + if (ast == 0) + { + ast = AnimCurState(); + } + return (ast == 0) ? 0.0f : ast->Data->Duration; +} + +F32 zNPCCommon::AnimTimeRemain(xAnimState* ast) +{ + return (AnimDuration(ast) - AnimTimeCurrent()); +} + +F32 zNPCCommon::AnimTimeCurrent() +{ + return model->Anim->Single->Time; +} + +xVec3* zNPCCommon::MatPosSet(xVec3* pos) +{ + if (pos != NULL) + { + xVec3Copy((xVec3*)&model->Mat->pos, pos); + } + return (xVec3*)&model->Mat->pos; +} + S32 NPCC_NPCIsConversing() { return g_isConversation; @@ -344,7 +412,8 @@ xAnimTable* ZNPC_AnimTable_Common() { xAnimTable* table = xAnimTableNew("zNPCCommon", NULL, 0x0); - xAnimTableNewState(table, "Idle01", 0x110, 0x1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, "Idle01", 0x110, 0x1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); return table; } @@ -353,10 +422,14 @@ xAnimTable* ZNPC_AnimTable_LassoGuide() { xAnimTable* table = xAnimTableNew("LassoGuides", NULL, 0x0); - xAnimTableNewState(table, g_strz_lassanim[LassoGuide_Grab01], 0x0, 0x1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_lassanim[LassoGuide_Hold01], 0x0, 0x1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_lassanim[LassoGuide_Grab01], 0x0, 0x1, 1.0f, NULL, NULL, 0.0f, + NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_lassanim[LassoGuide_Hold01], 0x0, 0x1, 1.0f, NULL, NULL, 0.0f, + NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewTransition(table, g_strz_lassanim[LassoGuide_Grab01], g_strz_lassanim[LassoGuide_Hold01], NULL, NULL, 0x10, 0x0, 0.0f, 0.0f, 0, 0, 0.0f, NULL); + xAnimTableNewTransition(table, g_strz_lassanim[LassoGuide_Grab01], + g_strz_lassanim[LassoGuide_Hold01], NULL, NULL, 0x10, 0x0, 0.0f, 0.0f, + 0, 0, 0.0f, NULL); return table; } diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 463202dac..9ce4342c6 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -181,7 +181,7 @@ struct zNPCSettings : xDynAsset U8 allowPatrol; U8 allowWander; U8 reduceCollide; - S8 useNavSplines; + U8 useNavSplines; S8 pad[3]; S8 allowChase; S8 allowAttack; @@ -430,6 +430,7 @@ struct zNPCCommon : xNPCBasic //Size of zNPCCommon: 0x2A0 xAnimState* AnimCurState(); xAnimSingle* AnimCurSingle(); U32 AnimCurStateID(); + U32 CanDoSplines(); void GiveReward(); S32 SndPlayFromSFX(xSFX* sfx, U32* sid_played); S32 SndPlayRandom(en_NPC_SOUND sndtype); @@ -456,6 +457,7 @@ struct zNPCCommon : xNPCBasic //Size of zNPCCommon: 0x2A0 xVec3* Pos(); RwMatrix* BoneMat(S32 unk) const; RwV3d* BonePos(S32 unk) const; + xVec3* MatPosSet(xVec3* pos); void XZVecToPlayer(xVec3* unk1, F32* unk2); F32 XZDstSqToPos(const xVec3* unk1, xVec3* unk2, F32* unk3); void XZVecToPos(xVec3* unk1, const xVec3* unk2, F32* unk3); @@ -632,8 +634,8 @@ void ZNPC_Destroy_Common(xFactoryInst* inst); void zNPCCommon_ScenePrepare(); void zNPCCommon_ScenePostInit(); void zNPCCommon_SceneFinish(); -void zNPCPlyrSnd_Reset(); -void zNPCPlyrSnd_Update(F32 dt); +static void zNPCPlyrSnd_Reset(); +static void zNPCPlyrSnd_Update(F32 dt); void zNPCCommon_SceneReset(); void ZNPC_Destroy_Common(xFactoryInst* inst); void zNPCSettings_MakeDummy(); diff --git a/src/SB/Game/zNPCTypeRobot.h b/src/SB/Game/zNPCTypeRobot.h index d0d8f9770..0c0e7de22 100644 --- a/src/SB/Game/zNPCTypeRobot.h +++ b/src/SB/Game/zNPCTypeRobot.h @@ -147,7 +147,7 @@ struct zNPCRobot : zNPCCommon U8 ColChkByFlags() const; zNPCLassoInfo* PRIV_GetLassoData(); S32 LassoSetup(); - + F32 GetParm(en_npcparm, zMovePoint**); F32 FacePlayer(F32 dt, F32 spd_turn); // vTable (zNPCRobot)