From 5a221a5496d29bfed8d6c3a9c168b2e7a7943d8b Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Fri, 11 Apr 2025 00:10:22 -0500 Subject: [PATCH 1/6] zNPCTypeCommon: Add declaration for zNPCCommon::HaveLOSToPos --- src/SB/Game/zNPCTypeCommon.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 773b5f3fa..65bf44702 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -418,6 +418,7 @@ struct zNPCCommon : xNPCBasic //Size of zNPCCommon: 0x2A0 bool IsMountableType(en_ZBASETYPE type); void MvptReset(zMovePoint* nav_goto); S32 MvptCycle(); + S32 HaveLOSToPos(xVec3*, float, xScene*, xBase*, xCollis*); void ModelScaleSet(F32 x, F32 y, F32 z); void ModelScaleSet(F32 unk); void ModelScaleSet(const xVec3* vec); From 6a520d659e5a6894c55c9f46fe65077e8b41330c Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Fri, 11 Apr 2025 00:11:08 -0500 Subject: [PATCH 2/6] zNPCTypeAmbient: Add declarations for zNPCJellly ActLikeOctopus and JellyBoneWorldPos --- src/SB/Game/zNPCTypeAmbient.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SB/Game/zNPCTypeAmbient.h b/src/SB/Game/zNPCTypeAmbient.h index 0a2bf955f..5d402e2d0 100644 --- a/src/SB/Game/zNPCTypeAmbient.h +++ b/src/SB/Game/zNPCTypeAmbient.h @@ -47,10 +47,12 @@ struct zNPCJelly : zNPCAmbient void PlayWithAlpha(F32 unk); void PlayWithAnimSpd(); void PumpFaster(); + xVec3* JellyBoneWorldPos(xVec3* pos, S32 idx_request) const; void PlayWithLightnin(); void SetAlpha(F32 alpha); U32 AnimPick(S32 animID, en_NPC_GOAL_SPOT gspot, xGoal* goal); + void ActLikeOctopus(); }; struct zNPCNeptune : zNPCAmbient From b2f512c79539d33137b302bcf605f0b1eea339bf Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Fri, 11 Apr 2025 00:11:41 -0500 Subject: [PATCH 3/6] zFX: Add overload declarations for zFX_SpawnBubbleTrail --- src/SB/Game/zFX.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SB/Game/zFX.h b/src/SB/Game/zFX.h index 3918de9a5..35ff9442b 100644 --- a/src/SB/Game/zFX.h +++ b/src/SB/Game/zFX.h @@ -88,8 +88,11 @@ void xDebugAddTweak(const char* unk1, const char* unk2, const tweak_callback* un xFXRing* zFXMuscleArmWave(const xVec3* pos); +void zFX_SpawnBubbleTrail(const xVec3*, unsigned int); void zFX_SpawnBubbleTrail(const xVec3* pos, unsigned int num, const xVec3* pos_rnd, const xVec3* vel_rnd); +void zFX_SpawnBubbleTrail(const xVec3*, const xVec3*, const xVec3*, const xVec3*, unsigned int, + const xVec3*, const xVec3*, float); void zFX_SpawnBubbleMenuTrail(const xVec3* pos, U32 num, const xVec3* pos_rnd, const xVec3* vel_rnd); From df37c534273a0b6a74f5d7bf70aef4b5fc7667b0 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Fri, 11 Apr 2025 00:11:56 -0500 Subject: [PATCH 4/6] xFX: Add overload declaration for xFXStreakUpdate --- src/SB/Core/x/xFX.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SB/Core/x/xFX.h b/src/SB/Core/x/xFX.h index d09479ad1..4f85a47e0 100644 --- a/src/SB/Core/x/xFX.h +++ b/src/SB/Core/x/xFX.h @@ -110,6 +110,7 @@ void xFXFireworksLaunch(F32 countdownTime, const xVec3* pos, F32 fuelTime); void xFXFireworksUpdate(F32 dt); void xFXStreakInit(); void xFXStreakUpdate(F32 dt); +void xFXStreakUpdate(U32 streakID, const xVec3*, const xVec3*); void xFXStreakRender(); void xFXStreakStop(U32); void xFXShineInit(); From 1e5295e2e78ee3085d65fc201f35d596477eed7a Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Fri, 11 Apr 2025 00:13:00 -0500 Subject: [PATCH 5/6] zNPCGoalAmbient: Nearly 100% match for all zNPCGoalJellyBumped functions --- src/SB/Game/zNPCGoalAmbient.cpp | 199 ++++++++++++++++++++++++++++++++ src/SB/Game/zNPCGoalAmbient.h | 19 +++ 2 files changed, 218 insertions(+) diff --git a/src/SB/Game/zNPCGoalAmbient.cpp b/src/SB/Game/zNPCGoalAmbient.cpp index 1604e2dba..283e44241 100644 --- a/src/SB/Game/zNPCGoalAmbient.cpp +++ b/src/SB/Game/zNPCGoalAmbient.cpp @@ -1,9 +1,208 @@ #include +#include "xMath.h" #include "xMath3.h" #include "xVec3.h" #include "zNPCGoalAmbient.h" #include "zNPCSndTable.h" +#include "xMathInlines.h" +#include "zNPCSupplement.h" +#include "zGlobals.h" + +S32 zNPCGoalJellyBumped::Enter(F32 dt, void* updCtxt) +{ + zNPCJelly* npc; + xVec3 dir_aim; + + npc = (zNPCJelly*)psyche->clt_owner; + + ExtractAimDir(&dir_aim); + CalcEndPoint(&pos_grindin, &dir_aim); + + pos_bumpin = *npc->Pos(); + + npc->cnt_angerLevel -= 40; + npc->hitpoints--; + + npc->SndPlayRandom(NPC_STYP_OUCH); + + npc->ActLikeOctopus(); + + StreakPrep(); + + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalJellyBumped::Exit(F32 dt, void* updCtxt) +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + npc->VelStop(); + + StreakDone(); + + npc->SndPlayRandom(NPC_STYP_DEATHJELLY); + npc->ActLikeOctopus(); + + return zNPCGoalPushAnim::Exit(dt, updCtxt); +} + +S32 zNPCGoalJellyBumped::Process(en_trantype* trantyp, F32 dt, void* updCxt, xScene* xscn) +{ + S32 nextgoal = 0; + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + xVec3 pos; + F32 pam; + + PlayWithAnimSpd(); + MoveSwoosh(dt); + + npc->JellyBoneWorldPos(&pos, -1); + + zFX_SpawnBubbleTrail(&pos, 0x4); + + StreakUpdate(); + + pam = npc->AnimTimeRemain(NULL) / npc->AnimDuration(NULL); + pam = CLAMP(pam, 0.01f, 1.0f); + + if (npc->hitpoints < 1) + { + npc->SetAlpha(pam); + } + + if (npc->hitpoints < 1 && pam < 0.01f) + { + *trantyp = GOAL_TRAN_SET; + nextgoal = 'NGN5'; + } + + if (*trantyp != GOAL_TRAN_NONE) + { + return nextgoal; + } + + return zNPCGoalPushAnim::Process(trantyp, dt, updCxt, xscn); +} + +void LERP(float dt, xVec3* pos_update, const xVec3*, const xVec3*); +F32 SMOOTH(float, float, float); + +void zNPCGoalJellyBumped::MoveSwoosh(F32 dt) +{ + F32 pos_factor; + xVec3 pos_update; + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + + pos_factor = SQ(npc->AnimTimeRemain(NULL)) / SQ(npc->AnimDuration(NULL)); + pos_factor = 1.0f - pos_factor; + pos_factor = CLAMP(pos_factor, 0.01f, 1.0f); + + LERP(pos_factor, &pos_update, &pos_bumpin, &pos_grindin); + npc->frame->mat.pos = pos_update; + + npc->frame->mode |= 0x1; +} + +void zNPCGoalJellyBumped::PlayWithAnimSpd() +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + + F32 pos_factor = npc->AnimTimeRemain(NULL) / npc->AnimDuration(NULL); + pos_factor = CLAMP(pos_factor, 0.01f, 1.0f); + pos_factor = SMOOTH(pos_factor, 1.0f, 3.0f); + + npc->AnimCurSingle()->CurrentSpeed = pos_factor; +} + +void zNPCGoalJellyBumped::StreakPrep() +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + if (npc->SelfType() == 'NTA1') + { + streakID = NPCC_StreakCreate(NPC_STRK_TOSSEDJELLYBLUE); + } + else + { + streakID = NPCC_StreakCreate(NPC_STRK_TOSSEDJELLY); + } +} + +void zNPCGoalJellyBumped::StreakDone() +{ + xFXStreakStop(streakID); + streakID = 0xDEAD; +} + +void zNPCGoalJellyBumped::StreakUpdate() +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + xVec3 bone_pos1; + xVec3 bone_pos2; + + npc->JellyBoneWorldPos(&bone_pos1, 2); + npc->JellyBoneWorldPos(&bone_pos2, 3); + + xFXStreakUpdate(streakID, (const xVec3*)&bone_pos1, (const xVec3*)&bone_pos2); +} + +void zNPCGoalJellyBumped::ExtractAimDir(xVec3* dir_aim) +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + F32 length; + + if (flg_info & 0x10) + { + npc->XZVecToPos(dir_aim, (const xVec3*)&pos_bumper, NULL); + } + else + { + npc->XZVecToPlayer(dir_aim, NULL); + } + + flg_info = 0x0; + + xVec3Inv(dir_aim, dir_aim); + + dir_aim->y = 0.0f; + + length = dir_aim->length(); + if (length < 1e-5f) + { + *dir_aim = *NPCC_faceDir(&globals.player.ent); + } + else + { + *dir_aim /= length; + } +} + +F32 zNPCGoalJellyBumped::CalcEndPoint(xVec3* pos_end, const xVec3* dir_aim) +{ + xCollis colrec; + S32 rc; + + F32 dst_toEndPnt = 4.0f; + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + xVec3 vec = *dir_aim * dst_toEndPnt; + xVec3 pos = vec + *npc->Pos(); + + memset(&colrec, 0, sizeof(colrec)); + colrec.flags = 0x1F00; + + rc = npc->HaveLOSToPos(&pos, 4.0f, globals.sceneCur, NULL, &colrec); + if (rc) + { + *pos_end = pos; + dst_toEndPnt = 4.0f; + } + else + { + dst_toEndPnt = colrec.dist; + *pos_end = *npc->Pos() + *dir_aim * dst_toEndPnt; + } + + return dst_toEndPnt; +} S32 zNPCGoalJellyAttack::Enter(F32 arg0, void* arg1) { diff --git a/src/SB/Game/zNPCGoalAmbient.h b/src/SB/Game/zNPCGoalAmbient.h index 60203fbef..937c26be3 100644 --- a/src/SB/Game/zNPCGoalAmbient.h +++ b/src/SB/Game/zNPCGoalAmbient.h @@ -33,4 +33,23 @@ struct zNPCGoalJellyAttack : zNPCGoalPushAnim S32 ZapperUpdate(); }; +struct zNPCGoalJellyBumped : zNPCGoalPushAnim +{ + xVec3 pos_bumper; + xVec3 pos_bumpin; + xVec3 pos_grindin; + U32 streakID; + + S32 Enter(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); + S32 Process(en_trantype* trantyp, F32 dt, void* updCxt, xScene* xscn); + void MoveSwoosh(F32 dt); + void PlayWithAnimSpd(); + void StreakPrep(); + void StreakDone(); + void StreakUpdate(); + void ExtractAimDir(xVec3* dir); + F32 CalcEndPoint(xVec3* pos_end, const xVec3* dir_aim); +}; + #endif From f4fa63dc8927eb20e714682b6e165e250ff97de2 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Fri, 11 Apr 2025 00:14:38 -0500 Subject: [PATCH 6/6] zNPCGoalAmbient: Fix flipped registers in CalcEndPoint implementation --- src/SB/Game/zNPCGoalAmbient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SB/Game/zNPCGoalAmbient.cpp b/src/SB/Game/zNPCGoalAmbient.cpp index 283e44241..be4f30b7d 100644 --- a/src/SB/Game/zNPCGoalAmbient.cpp +++ b/src/SB/Game/zNPCGoalAmbient.cpp @@ -184,7 +184,7 @@ F32 zNPCGoalJellyBumped::CalcEndPoint(xVec3* pos_end, const xVec3* dir_aim) F32 dst_toEndPnt = 4.0f; zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; xVec3 vec = *dir_aim * dst_toEndPnt; - xVec3 pos = vec + *npc->Pos(); + xVec3 pos = *npc->Pos() + vec; memset(&colrec, 0, sizeof(colrec)); colrec.flags = 0x1F00;