diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fa2dad80..e3c1b6aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -67,20 +67,30 @@ jobs: name: ${{ matrix.version }}_maps path: build/${{ matrix.version }}/**/*.MAP - - name: Generate Progress Report + - name: Generate Progress Reports if: github.ref == 'refs/heads/main' run: | ./objdiff-cli report generate -o progress.json + git log -1 --pretty='{"id": "%H", "email": "%ae", "time": "%ad", "message": "%s"}' --date=format:"%Y-%m-%dT%H:%M:%S" > progress-commit.json + git checkout HEAD~1 + rm -rf ./build/ + ninja all_source + ./objdiff-cli report generate -o previous.json - - name: Save Artifact + - name: Save Progress Artifacts if: github.ref == 'refs/heads/main' uses: actions/upload-artifact@v4 with: name: progress - path: progress.json + path: | + progress.json + previous.json + progress-commit.json website: runs-on: ubuntu-latest + permissions: + contents: write needs: build if: github.ref == 'refs/heads/main' steps: @@ -89,7 +99,7 @@ jobs: with: repository: bfbbdecomp/website - - name: Download artifact + - name: Download Progress Artifacts uses: actions/download-artifact@v4 with: name: progress @@ -110,3 +120,20 @@ jobs: folder: dist # The folder the action should deploy. clean: true single-commit: true + + - name: Commit Changes + continue-on-error: true + run: | + git status + git pull origin main + git config --global user.name "BFBB Actions Bot" + git config --global user.email "actions@github.com" + git add . + git commit -m "automated commit cache update" + + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.WEBSITE_TOKEN }} + repository: bfbbdecomp/website + branch: ${{ github.ref }} diff --git a/configure.py b/configure.py index 17a26eb2..2d0479bd 100644 --- a/configure.py +++ b/configure.py @@ -283,7 +283,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Core/x/xCamera.cpp"), Object(NonMatching, "SB/Core/x/xClimate.cpp"), Object(NonMatching, "SB/Core/x/xCollide.cpp"), - Object(NonMatching, "SB/Core/x/xCollideFast.cpp"), + Object(Matching, "SB/Core/x/xCollideFast.cpp"), Object(NonMatching, "SB/Core/x/xColor.cpp"), Object(Matching, "SB/Core/x/xCounter.cpp"), Object(NonMatching, "SB/Core/x/xCutscene.cpp"), @@ -302,7 +302,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Core/x/xHud.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Core/x/xHudFontMeter.cpp"), Object(NonMatching, "SB/Core/x/xHudMeter.cpp"), - Object(NonMatching, "SB/Core/x/xHudModel.cpp"), + Object(Equivalent, "SB/Core/x/xHudModel.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Core/x/xHudUnitMeter.cpp"), Object(Matching, "SB/Core/x/xIni.cpp"), Object(NonMatching, "SB/Core/x/xMath.cpp"), @@ -345,14 +345,14 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Game/zDispatcher.cpp"), Object(NonMatching, "SB/Game/zEGenerator.cpp"), Object(NonMatching, "SB/Game/zEnt.cpp"), - Object(NonMatching, "SB/Game/zEntButton.cpp"), + Object(Equivalent, "SB/Game/zEntButton.cpp"), Object(NonMatching, "SB/Game/zEntCruiseBubble.cpp"), Object(NonMatching, "SB/Game/zEntDestructObj.cpp"), Object(NonMatching, "SB/Game/zEntHangable.cpp"), Object(NonMatching, "SB/Game/zEntPickup.cpp"), Object(NonMatching, "SB/Game/zEntPlayer.cpp"), Object(NonMatching, "SB/Game/zEntSimpleObj.cpp"), - Object(NonMatching, "SB/Game/zEntTrigger.cpp"), + Object(Matching, "SB/Game/zEntTrigger.cpp", extra_cflags=["-sym on"]), Object(Matching, "SB/Game/zEnv.cpp"), Object(Matching, "SB/Game/zEvent.cpp"), Object(Matching, "SB/Game/zFeet.cpp"), @@ -360,7 +360,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Game/zFX.cpp"), Object(NonMatching, "SB/Game/zGame.cpp"), Object(Equivalent, "SB/Game/zGameExtras.cpp"), - Object(NonMatching, "SB/Game/zGameState.cpp"), + Object(Equivalent, "SB/Game/zGameState.cpp"), Object(NonMatching, "SB/Game/zGust.cpp"), Object(NonMatching, "SB/Game/zHud.cpp"), Object(NonMatching, "SB/Game/zLasso.cpp"), @@ -406,7 +406,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Core/gc/iMix.c"), Object(NonMatching, "SB/Core/gc/iModel.cpp"), Object(NonMatching, "SB/Core/gc/iMorph.cpp"), - Object(NonMatching, "SB/Core/gc/iPad.cpp"), + Object(Equivalent, "SB/Core/gc/iPad.cpp"), Object(NonMatching, "SB/Core/gc/iParMgr.cpp"), Object(NonMatching, "SB/Core/gc/isavegame.cpp"), Object(NonMatching, "SB/Core/gc/iScrFX.cpp"), @@ -416,9 +416,9 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Core/gc/ngcrad3d.c"), Object(Matching, "SB/Game/zNPCGoals.cpp"), Object(NonMatching, "SB/Game/zNPCGoalCommon.cpp"), # wrong function order - Object(NonMatching, "SB/Game/zNPCGoalStd.cpp"), + Object(NonMatching, "SB/Game/zNPCGoalStd.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Game/zNPCGoalRobo.cpp"), - Object(NonMatching, "SB/Game/zNPCGoalTiki.cpp"), + Object(Matching, "SB/Game/zNPCGoalTiki.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Game/zNPCMessenger.cpp"), Object(NonMatching, "SB/Game/zNPCMgr.cpp"), Object(Matching, "SB/Game/zNPCTypes.cpp"), @@ -431,7 +431,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Core/x/xBehaviour.cpp"), # breaks build (weak functions) Object(NonMatching, "SB/Core/x/xBehaveGoalSimple.cpp"), # breaks build (weak functions) Object(NonMatching, "SB/Core/x/xSkyDome.cpp"), - Object(NonMatching, "SB/Core/x/xRMemData.cpp"), + Object(Matching, "SB/Core/x/xRMemData.cpp", extra_cflags=["-sym on"]), Object(Matching, "SB/Core/x/xFactory.cpp"), Object(NonMatching, "SB/Core/x/xNPCBasic.cpp"), Object(NonMatching, "SB/Game/zEntPlayerBungeeState.cpp"), @@ -450,13 +450,13 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(Matching, "SB/Game/zCamMarker.cpp"), Object(NonMatching, "SB/Game/zGoo.cpp"), Object(NonMatching, "SB/Game/zGrid.cpp"), - Object(NonMatching, "SB/Game/zNPCGoalScript.cpp"), + Object(Matching, "SB/Game/zNPCGoalScript.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Game/zNPCSndTable.cpp"), Object(NonMatching, "SB/Game/zNPCSndLists.cpp"), Object(NonMatching, "SB/Game/zNPCTypeDuplotron.cpp"), Object(NonMatching, "SB/Core/x/xModelBucket.cpp"), Object(NonMatching, "SB/Game/zShrapnel.cpp"), - Object(NonMatching, "SB/Game/zNPCGoalDuplotron.cpp"), + Object(Matching, "SB/Game/zNPCGoalDuplotron.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Game/zNPCSpawner.cpp"), Object(NonMatching, "SB/Game/zEntTeleportBox.cpp"), Object(Matching, "SB/Game/zBusStop.cpp"), @@ -468,8 +468,8 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(Matching, "SB/Game/zNPCTypeTest.cpp"), Object(NonMatching, "SB/Game/zNPCTypeSubBoss.cpp"), Object(NonMatching, "SB/Game/zNPCTypeBoss.cpp"), - Object(NonMatching, "SB/Game/zNPCGoalVillager.cpp"), - Object(NonMatching, "SB/Game/zNPCGoalSubBoss.cpp"), + Object(NonMatching, "SB/Game/zNPCGoalVillager.cpp", extra_cflags=["-sym on"]), + Object(Matching, "SB/Game/zNPCGoalSubBoss.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Core/x/xShadowSimple.cpp"), Object(NonMatching, "SB/Core/x/xUpdateCull.cpp"), Object(NonMatching, "SB/Game/zDiscoFloor.cpp"), @@ -477,7 +477,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(NonMatching, "SB/Game/zNPCTypeKingJelly.cpp"), Object(Matching, "SB/Game/zNPCGoalBoss.cpp"), Object(NonMatching, "SB/Game/zNPCTypePrawn.cpp"), - Object(NonMatching, "SB/Game/zNPCTypeBossSB1.cpp"), + Object(Equivalent, "SB/Game/zNPCTypeBossSB1.cpp"), Object(NonMatching, "SB/Game/zNPCTypeBossSB2.cpp"), Object(Matching, "SB/Core/x/xJaw.cpp"), Object(NonMatching, "SB/Game/zNPCTypeBossPatrick.cpp"), diff --git a/include/dolphin/dolphin.h b/include/dolphin/dolphin.h index 150e15e2..31e1f184 100644 --- a/include/dolphin/dolphin.h +++ b/include/dolphin/dolphin.h @@ -165,9 +165,43 @@ typedef struct OSContext u32 gqr[8]; u32 psf_pad; f64 psf[32]; - } OSContext; + +#define PAD_MAX_CONTROLLERS 4 + +#define PAD_BUTTON_LEFT 0x0001 +#define PAD_BUTTON_RIGHT 0x0002 +#define PAD_BUTTON_DOWN 0x0004 +#define PAD_BUTTON_UP 0x0008 +#define PAD_TRIGGER_Z 0x0010 +#define PAD_TRIGGER_R 0x0020 +#define PAD_TRIGGER_L 0x0040 +#define PAD_BUTTON_A 0x0100 +#define PAD_BUTTON_B 0x0200 +#define PAD_BUTTON_X 0x0400 +#define PAD_BUTTON_Y 0x0800 +#define PAD_BUTTON_START 0x1000 + +#define PAD_ERR_NONE 0 +#define PAD_ERR_NO_CONTROLLER -1 +#define PAD_ERR_NOT_READY -2 +#define PAD_ERR_TRANSFER -3 + +typedef struct PADStatus +{ + u16 button; + s8 stickX; + s8 stickY; + s8 substickX; + s8 substickY; + u8 triggerLeft; + u8 triggerRight; + u8 analogA; + u8 analogB; + s8 err; +} PADStatus; + extern volatile OSHeapHandle __OSCurrHeap; #define OSAlloc(size) OSAllocFromHeap(__OSCurrHeap, (size)) @@ -196,6 +230,9 @@ OSTime OSGetTime(); void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* td); BOOL PADInit(); void PADControlMotor(int chan, u32 command); +void PADRead(PADStatus* status); +void PADClamp(PADStatus* status); +void PADReset(u32 mask); void AXQuit(); void AXFreeVoice(_AXVPB*); void OSSetSoundMode(u32 mode); diff --git a/src/SB/Core/gc/iAnim.h b/src/SB/Core/gc/iAnim.h index 078da2a1..8763ea9f 100644 --- a/src/SB/Core/gc/iAnim.h +++ b/src/SB/Core/gc/iAnim.h @@ -7,8 +7,9 @@ extern U8* giAnimScratch; void iAnimInit(); U32 iAnimBoneCount(void* RawData); -void iAnimBlend(F32 BlendFactor, F32 BlendRecip, U16* BlendTimeOffset, - F32* BoneTable, U32 BoneCount, xVec3* Tran1, xQuat* Quat1, xVec3* Tran2, - xQuat* Quat2, xVec3* TranDest, xQuat* QuatDest); +void iAnimBlend(F32 BlendFactor, F32 BlendRecip, U16* BlendTimeOffset, F32* BoneTable, + U32 BoneCount, xVec3* Tran1, xQuat* Quat1, xVec3* Tran2, xQuat* Quat2, + xVec3* TranDest, xQuat* QuatDest); +void iAnimEval(void* RawData, float time, unsigned int flags, class xVec3* tran, class xQuat* quat); #endif diff --git a/src/SB/Core/gc/iModel.h b/src/SB/Core/gc/iModel.h index 0fcffc81..90a559d8 100644 --- a/src/SB/Core/gc/iModel.h +++ b/src/SB/Core/gc/iModel.h @@ -15,8 +15,9 @@ void iModelSetMaterialTexture(RpAtomic* model, void* texture); void iModelResetMaterial(RpAtomic* model); S32 iModelCullPlusShadow(RpAtomic* model, RwMatrix* mat, xVec3* shadowVec, S32* shadowOutside); void iModelTagEval(RpAtomic* model, const xModelTag* tag, RwMatrixTag* mat, xVec3* dest); -U32 iModelTagSetup(xModelTag tag, RpAtomic* model, F32 x, F32 y, F32 z); +U32 iModelTagSetup(xModelTag* tag, RpAtomic* model, F32 x, F32 y, F32 z); void iModelSetMaterialAlpha(RpAtomic* model, U8 alpha); +void iModelMaterialMul(RpAtomic* model, F32 rm, F32 gm, F32 bm); RpAtomic* iModelFileNew(void* buffer, U32 size); void iModelRender(RpAtomic* model, RwMatrix* mat); void iModelUnload(RpAtomic* userdata); diff --git a/src/SB/Core/gc/iPad.cpp b/src/SB/Core/gc/iPad.cpp index efa9b71f..584dd3c5 100644 --- a/src/SB/Core/gc/iPad.cpp +++ b/src/SB/Core/gc/iPad.cpp @@ -2,7 +2,16 @@ #include #include "iPad.h" +#include "xGlobals.h" #include "xPad.h" +#include "xTRC.h" +#include "zGlobals.h" + +extern xGlobals* xglobals; +extern zGlobals globals; + +PADStatus sPadData[PAD_MAX_CONTROLLERS]; + S32 iPadInit() { @@ -10,17 +19,125 @@ S32 iPadInit() return 1; } -#if 0 _tagxPad* iPadEnable(_tagxPad* pad, S16 port) { pad->port = port; pad->slot = 0; pad->state = ePad_Enabled; - // *(undefined4*)(gTrcPad + (int)*(short*)(pad + 0x54) * 0xc + 8) = 2; - // *(uint*)(pad + 0x40) = *(uint*)(pad + 0x40) | 3; - // *(uint*)(pad + 0x40) = *(uint*)(pad + 0x40) | 4; + gTrcPad[pad->port].state = TRC_PadInserted; + pad->flags |= 3; + pad->flags |= 4; + return pad; +} + +S32 iPadConvStick(F32 value) +{ + F32 clampedValue; + if (value > 40.0f) + { + clampedValue = 40.0f; + } + else if (value < -40.0f) + { + clampedValue = -40.0f; + } + else + { + clampedValue = value; + } + + F32 convertedValue = 3.2f * clampedValue; + + if (convertedValue > 127.0f) + { + convertedValue = 127.0f; + } + else if (convertedValue < -127.0f) + { + convertedValue = -127.0f; + } + + return convertedValue; +} + +S32 iPadUpdate(_tagxPad* pad, U32* on) +{ + U16 buttons; + U32 temp_on; + + if (pad->port == 0) + { + PADRead(sPadData); + PADClamp(sPadData); + } + + PADStatus* padData = (PADStatus*)&sPadData; + switch (padData[pad->port].err) + { + case PAD_ERR_NO_CONTROLLER: + xTRCPad(pad->port, TRC_PadMissing); + PADReset(0x80000000 >> pad->port); + goto defaultError; + + case PAD_ERR_NOT_READY: case PAD_ERR_TRANSFER: + return 0; + + default: defaultError: + return 0; + + case PAD_ERR_NONE: + temp_on = iPadConvFromGCN(padData[pad->port].button, 1, 0x80); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 2, 0x20); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 4, 0x40); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 8, 0x10); + buttons = sPadData[pad->port].button; + + if (buttons & 0x10) + { + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x2000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x200); + if (sPadData[pad->port].triggerLeft >= 0x18) + { + temp_on |= 0x200; + } + if (sPadData[pad->port].triggerRight >= 0x18) + { + temp_on |= 0x2000; + } + temp_on |= 0x100000; + } + else + { + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x1000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x100); + if (sPadData[pad->port].triggerLeft >= 0x18) + { + temp_on |= 0x100; + } + if (sPadData[pad->port].triggerRight >= 0x18) + { + temp_on |= 0x1000; + } + } + + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x100, 0x10000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x200, 0x80000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x800, 0x40000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x400, 0x20000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x1000, 0x1); + (*on) = temp_on; + + pad->analog1.x = iPadConvStick(sPadData[pad->port].stickX); + pad->analog1.y = -iPadConvStick(sPadData[pad->port].stickY); // Scheduling memes. + pad->analog2.x = iPadConvStick(sPadData[pad->port].substickX); + pad->analog2.y = -iPadConvStick(sPadData[pad->port].substickY); // Same as above. + if (gTrcPad[pad->port].state != TRC_PadInserted) + { + xTRCPad(pad->port, TRC_PadInserted); + } + } + return 1; } -#endif S32 iPadConvFromGCN(U32 a, U32 b, U32 c) { @@ -33,6 +150,11 @@ void iPadRumbleFx(_tagxPad* p, _tagxRumble* r, F32 time_passed) { } +void iPadStopRumble() +{ + PADControlMotor(mPad[globals.currentActivePad].port, 0); // Scheduling memes. +} + void iPadStopRumble(_tagxPad* pad) { PADControlMotor(pad->port, 0); diff --git a/src/SB/Core/gc/iPad.h b/src/SB/Core/gc/iPad.h index e4d5492d..a35fdb25 100644 --- a/src/SB/Core/gc/iPad.h +++ b/src/SB/Core/gc/iPad.h @@ -13,6 +13,10 @@ struct _tagxRumble; S32 iPadInit(); _tagxPad* iPadEnable(_tagxPad* pad, S16 port); +S32 iPadConvStick(float value); +S32 iPadUpdate(_tagxPad* pad, U32* on); +S32 iPadConvFromGCN(U32 a, U32 b, U32 c); +void iPadRumbleFx(_tagxPad* p, _tagxRumble* r, F32 time_passed); void iPadStopRumble(_tagxPad* pad); void iPadStopRumble(); void iPadStartRumble(_tagxPad* pad, _tagxRumble* rumble); diff --git a/src/SB/Core/x/xBase.h b/src/SB/Core/x/xBase.h index 030d05be..a6f32691 100644 --- a/src/SB/Core/x/xBase.h +++ b/src/SB/Core/x/xBase.h @@ -25,7 +25,7 @@ struct xBase U8 linkCount; U16 baseFlags; xLinkAsset* link; - xBaseEventCB eventFunc; + xBaseEventCB eventFunc; // 0xC }; void xBaseInit(xBase* xb, xBaseAsset* asset); diff --git a/src/SB/Core/x/xBehaviour.h b/src/SB/Core/x/xBehaviour.h index 40358345..2ec31439 100644 --- a/src/SB/Core/x/xBehaviour.h +++ b/src/SB/Core/x/xBehaviour.h @@ -103,8 +103,9 @@ struct xPsyche : RyzMemData void ImmTranOff(); S32 ImmTranIsOn(); S32 HasGoal(S32 goal); - S32 GIDOfPending() const; + xGoal* GetCurGoal() const; S32 GIDOfActive() const; + S32 GIDOfPending() const; S32 Timestep(F32 dt, void* updCtxt); xGoal* FindGoal(S32 gid); S32 GoalSet(S32 gid, S32 r5); diff --git a/src/SB/Core/x/xBound.h b/src/SB/Core/x/xBound.h index 761f6386..132b7d2b 100644 --- a/src/SB/Core/x/xBound.h +++ b/src/SB/Core/x/xBound.h @@ -10,8 +10,7 @@ struct xBound { xQCData qcd; - // Offset: 0x20 - U8 type; + U8 type; // Offset: 0x20 (or 0x84) U8 pad[3]; union { diff --git a/src/SB/Core/x/xCollide.h b/src/SB/Core/x/xCollide.h index 1cd4a06b..ce1f0191 100644 --- a/src/SB/Core/x/xCollide.h +++ b/src/SB/Core/x/xCollide.h @@ -1,6 +1,7 @@ #ifndef XCOLLIDE_H #define XCOLLIDE_H +#include "xEnv.h" #include "xModel.h" #include "xQuickCull.h" #include "iMath3.h" @@ -18,7 +19,7 @@ struct xCollis U32 oid; void* optr; xModelInstance* mptr; - F32 dist; + F32 dist; // 0x30 xVec3 norm; xVec3 tohit; xVec3 depen; @@ -110,6 +111,10 @@ bool xSphereHitsVCircle(const xSphere& s, const xVec3& c, F32 r); bool xSphereHitsVCircle(const xVec3& sc, F32 sr, const xVec3& cc, F32 cr); U32 xSphereHitsModel(const xSphere* b, const xModelInstance* m, xCollis* coll); +S32 xParabolaHitsEnv(xParabola* p, xEnv* env, xCollis* colls); +void xParabolaEvalPos(const xParabola*, xVec3*, F32); +void xParabolaEvalVel(const xParabola*, xVec3*, F32); + void xVec3AddScaled(xVec3*, const xVec3*, F32); #endif diff --git a/src/SB/Core/x/xCollideFast.cpp b/src/SB/Core/x/xCollideFast.cpp index b5396175..32b6f97d 100644 --- a/src/SB/Core/x/xCollideFast.cpp +++ b/src/SB/Core/x/xCollideFast.cpp @@ -1,5 +1,6 @@ #include "xCollideFast.h" #include "iCollideFast.h" +#include "xMath.h" #include @@ -7,3 +8,29 @@ void xCollideFastInit(xScene* sc) { iCollideFastInit(sc); } + +U32 xRayHitsSphereFast(const xRay3* r, const xSphere* s) +{ + xVec3 length; + xVec3Sub(&length, &r->origin, &s->center); + F32 dVar3 = xVec3Dot(&length, &length) - SQR(s->r); + if (dVar3 <= 0.0f) + { + return 1; + } + + if (r->flags & (1 << 11) && dVar3 > r->max_t * (2.0f * s->r + r->max_t)) + { + return 0; + } + + F32 dot = xVec3Dot(&length, &r->dir); + return (dot >= 0.0f) ? 0 : (SQR(dot) >= dVar3); +} + +U32 xRayHitsBoxFast(const xRay3* r, const xBox* b) +{ + xIsect isect; + iBoxIsectRay(b, r, &isect); + return isect.penned <= 0.0f || isect.contained <= 0.0f; +} diff --git a/src/SB/Core/x/xEnt.h b/src/SB/Core/x/xEnt.h index b63d23f3..5fcb0f8e 100644 --- a/src/SB/Core/x/xEnt.h +++ b/src/SB/Core/x/xEnt.h @@ -86,13 +86,16 @@ struct xEntCollis U8 pen; U8 env_sidx; U8 env_eidx; + U8 npc_sidx; U8 npc_eidx; U8 dyn_sidx; U8 dyn_eidx; + U8 stat_sidx; U8 stat_eidx; U8 idx; + xCollis colls[18]; void (*post)(xEnt*, xScene*, F32, xEntCollis*); U32 (*depenq)(xEnt*, xEnt*, xScene*, F32, xCollis*); @@ -177,7 +180,7 @@ struct xEnt : xBase xShadowSimpleCache* simpShadow; xEntShadow* entShadow; anim_coll_data* anim_coll; - void* user_data; + void* user_data; // 0xCC }; // collision types diff --git a/src/SB/Core/x/xEntBoulder.h b/src/SB/Core/x/xEntBoulder.h index 000eb179..4564ba3d 100644 --- a/src/SB/Core/x/xEntBoulder.h +++ b/src/SB/Core/x/xEntBoulder.h @@ -77,6 +77,9 @@ void xEntBoulder_Init(void* ent, void* asset); void xEntBoulder_Init(xEntBoulder* ent, xEntAsset* asset); void xEntBoulder_BubbleBowl(F32 multiplier); void xEntBoulder_Setup(xEntBoulder* ent); +void xEntBoulder_Reset(xEntBoulder* ent, xScene* scene); +void xEntBoulder_RealBUpdate(xEnt* ent, xVec3* pos); +void xEntBoulder_Kill(xEntBoulder* ent); void xBoulderGenerator_Init(xBase& data, xDynAsset& asset, size_t); void xBoulderGenerator_Init(xBoulderGenerator* bg, xBoulderGeneratorAsset* asset); void xBoulderGenerator_Init(xBase& data, xDynAsset& asset); diff --git a/src/SB/Core/x/xEntMotion.h b/src/SB/Core/x/xEntMotion.h index 98984cce..603f6719 100644 --- a/src/SB/Core/x/xEntMotion.h +++ b/src/SB/Core/x/xEntMotion.h @@ -176,5 +176,6 @@ void xEntMotionDebugInit(U16 num_xems); void xEntMotionDebugExit(); void xEntMotionStop(xEntMotion* motion); void xEntMotionRun(xEntMotion* motion); +U32 xEntMotionIsStopped(const xEntMotion* motion); #endif diff --git a/src/SB/Core/x/xFactory.h b/src/SB/Core/x/xFactory.h index 086767d2..b3ed128c 100644 --- a/src/SB/Core/x/xFactory.h +++ b/src/SB/Core/x/xFactory.h @@ -12,8 +12,16 @@ struct xFactoryInst : RyzMemData xFactoryInst* nextprod; xFactoryInst* prevprod; - xFactoryInst(); - ~xFactoryInst(); + xFactoryInst() + { + itemType = 0; + prevprod = NULL; + nextprod = NULL; + } + + ~xFactoryInst() + { + } }; typedef xFactoryInst* (*XGOFTypeInfoCreator)(S32, RyzMemGrow*, void*); diff --git a/src/SB/Core/x/xGrid.h b/src/SB/Core/x/xGrid.h index b1a04bc8..bbfa803f 100644 --- a/src/SB/Core/x/xGrid.h +++ b/src/SB/Core/x/xGrid.h @@ -67,11 +67,13 @@ S32 xGridRemove(xGridBound* gridb); xGridBound** xGridGetCell(xGrid* grid, const xEnt* ent, S32& grx, S32& grz); void xGridGetCell(xGrid* grid, F32 posx, F32 posy, F32 posz, S32& grx, S32& grz); xGridBound* xGridIterFirstCell(xGrid* grid, S32 grx, S32 grz, xGridIterator& iter); -xGridBound* xGridIterFirstCell(xGrid* grid, F32 posx, F32, F32 posz, S32& grx, - S32& grz, xGridIterator& it); +xGridBound* xGridIterFirstCell(xGrid* grid, F32 posx, F32, F32 posz, S32& grx, S32& grz, + xGridIterator& it); xGridBound* xGridIterFirstCell(xGridBound** head, xGridIterator& it); xGridBound* xGridIterNextCell(xGridIterator& it); void xGridIterClose(xGridIterator& it); void xGridCheckPosition(xGrid* grid, xVec3* pos, xQCData* qcd, GridEntCallback hitCB, void* cbdata); +S32 xGridEntIsTooBig(xGrid* grid, const xEnt* ent); +S32 xGridAdd(xGrid* grid, xEnt* ent); #endif diff --git a/src/SB/Core/x/xHud.h b/src/SB/Core/x/xHud.h index 20a27f01..368e0f72 100644 --- a/src/SB/Core/x/xHud.h +++ b/src/SB/Core/x/xHud.h @@ -194,6 +194,7 @@ namespace xhud void destroy(); void update(F32 dt); void render(); + void render_model(xModelInstance& model, const render_context& context); bool linear_motive_update(widget& w, motive& m, F32); bool accelerate_motive_update(widget& w, motive& m, F32); diff --git a/src/SB/Core/x/xHudModel.cpp b/src/SB/Core/x/xHudModel.cpp index 2aa4f1ae..3b61a73f 100644 --- a/src/SB/Core/x/xHudModel.cpp +++ b/src/SB/Core/x/xHudModel.cpp @@ -1,29 +1,77 @@ #include "xHudModel.h" #include "xHud.h" +#include "xString.h" +#include #include -extern F32 lbl_803CCDE0; // 1.0f -extern F32 lbl_803CCDE4; // 0.0f -extern const char lbl_80252F38[]; - -#if 0 -// Fix the strings. xAnimTable* XHUD_AnimTable_Idle() { xAnimTable* table = xAnimTableNew("XHUD_AnimTable_Idle", NULL, 0); - xAnimTableNewState(table, "Idle01", 0x10, 1, lbl_803CCDE0, NULL, NULL, lbl_803CCDE4, NULL, NULL, + xAnimTableNewState(table, "Idle01", 0x10, 1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); return table; } -#endif - -#if 0 -// Works except for the string label offset. -char* xhud::model_asset::type_name() +namespace xhud { - return (char*)(lbl_80252F38 + 0x1B); -} -#endif + void model_widget::load(xBase& data, xDynAsset& asset, size_t) + { + init_base(data, asset, sizeof(xBase) + sizeof(model_widget)); + model_widget* widget = (model_widget*)(&data + 1); + new (widget) model_widget((model_asset&)asset); + } + + model_widget::model_widget(const model_asset& masset) + : widget(masset), mid(masset.model), model(NULL) + { + model = load_model(mid); + } + + void model_widget::destruct() + { + widget::destruct(); + } + + void model_widget::destroy() + { + destruct(); + } + + // Equivalent: scheduling + U32 model_widget::type() const + { + static U32 myid = xStrHash(model_asset::type_name()); + return myid; + } + + bool model_widget::is(U32 id) const + { + return id == model_widget::type() || widget::is(id); + } + + void model_widget::update(F32 dt) + { + widget::updater(dt); + + if (!visible() || rc.a <= (0.5f / 255.0f)) + { + return; + } + + xModelUpdate(model, dt); + xModelEval(model); + } + + void model_widget::render() + { + if (rc.a <= 0.0f) + { + return; + } + + render_model(*model, rc); + } + +} // namespace xhud diff --git a/src/SB/Core/x/xHudModel.h b/src/SB/Core/x/xHudModel.h index 270778fe..edd2e4ce 100644 --- a/src/SB/Core/x/xHudModel.h +++ b/src/SB/Core/x/xHudModel.h @@ -10,7 +10,10 @@ namespace xhud { U32 model; - char* type_name(); + static const char* type_name() + { + return "hud:model"; + } }; struct model_widget : widget @@ -18,7 +21,17 @@ namespace xhud U32 mid; xModelInstance* model; + model_widget(const model_asset&); + static void load(xBase& data, xDynAsset& asset, size_t); + + void destruct(); + + virtual void destroy(); + virtual U32 type() const; + virtual bool is(U32 id) const; + virtual void update(F32 dt); + virtual void render(); }; } // namespace xhud diff --git a/src/SB/Core/x/xListItem.h b/src/SB/Core/x/xListItem.h index 6f0acc9d..ff2d4598 100644 --- a/src/SB/Core/x/xListItem.h +++ b/src/SB/Core/x/xListItem.h @@ -9,6 +9,12 @@ template struct xListItem T* next; T* prev; + xListItem() { + flg_travFilter = 0; + prev = NULL; + next = NULL; + } + T* Next(); void Insert(T* list); T* RemHead(T** listhead); diff --git a/src/SB/Core/x/xMath3.h b/src/SB/Core/x/xMath3.h index 089e0d00..db96c9be 100644 --- a/src/SB/Core/x/xMath3.h +++ b/src/SB/Core/x/xMath3.h @@ -121,6 +121,7 @@ void xMat3x3Scale(xMat3x3* m, const xVec3* s); void xMat3x3ScaleC(xMat3x3* m, F32 x, F32 y, F32 z); void xMat3x3RMulRotY(xMat3x3* o, const xMat3x3* m, F32 t); void xMat3x3Mul(xMat3x3* o, const xMat3x3* a, const xMat3x3* b); +void xMat3x3SMul(xMat3x3*, const xMat3x3*, F32); void xBoxFromLine(xBox& box, const xLine3& line); void xBoxFromRay(xBox& box, const xRay3& ray); void xMat3x3Identity(xMat3x3* matrix); diff --git a/src/SB/Core/x/xModel.h b/src/SB/Core/x/xModel.h index 66f0499b..f6fdadad 100644 --- a/src/SB/Core/x/xModel.h +++ b/src/SB/Core/x/xModel.h @@ -135,6 +135,7 @@ void xModelAnimCollStart(xModelInstance& m); void xModelSetFrame(xModelInstance* modelInst, const xMat4x3* frame); xModelInstance* xModelInstanceAlloc(RpAtomic* data, void* object, U16 flags, U8 boneIndex, U8* boneRemap); +void xModelInstanceFree(xModelInstance* modelInst); void xModelInstanceAttach(xModelInstance* inst, xModelInstance* parent); void xModelRender(xModelInstance* modelInst); void xModelRender2D(const xModelInstance& model, const basic_rect& r, const xVec3& from, diff --git a/src/SB/Core/x/xNPCBasic.h b/src/SB/Core/x/xNPCBasic.h index 33201fea..760bfab5 100644 --- a/src/SB/Core/x/xNPCBasic.h +++ b/src/SB/Core/x/xNPCBasic.h @@ -21,6 +21,7 @@ enum en_npcdcat eNPCDCAT_Zero, eNPCDCAT_Seven = 7, eNPCDCAT_Eight = 8, + eNPCDCAT_Eleven = 11, }; struct xNPCBasic : xEnt, xFactoryInst @@ -61,7 +62,15 @@ struct xNPCBasic : xEnt, xFactoryInst xNPCBasic(S32); S32 SelfType() const; - void RestoreColFlags(); + void RestoreColFlags() + { + flags2.flg_colCheck = ColChkFlags(); + flags2.flg_penCheck = ColPenFlags(); + chkby = ColChkByFlags(); + penby = ColPenByFlags(); + pflags = PhysicsFlags(); + colFreq = -1; + } void DBG_PStatClear(); void DBG_PStatCont(en_npcperf stat); @@ -81,19 +90,38 @@ struct xNPCBasic : xEnt, xFactoryInst virtual void NewTime(xScene* xscn, F32 dt); virtual void Move(xScene* xscn, F32 dt, xEntFrame* frm); virtual S32 SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, - xBase* toParamWidget, S32* handled); + xBase* toParamWidget, S32* handled); virtual void Render(); virtual void Save(xSerial*) const; virtual void Load(xSerial*); virtual void CollideReview(); /* These most likely return a combination of XENT_COLLTYPE_* values */ - virtual U8 ColChkFlags() const; - virtual U8 ColPenFlags() const; - virtual U8 ColChkByFlags() const; - virtual U8 ColPenByFlags() const; + virtual U8 ColChkFlags() const + { + return 0; + } + + virtual U8 ColPenFlags() const + { + return 0; + } + + virtual U8 ColChkByFlags() const + { + return 0; + } + + virtual U8 ColPenByFlags() const + { + return 0; + } + + virtual U8 PhysicsFlags() const + { + return 0; + } - virtual U8 PhysicsFlags() const; virtual void Destroy(); }; diff --git a/src/SB/Core/x/xParEmitter.h b/src/SB/Core/x/xParEmitter.h index 394f0eef..7a208a44 100644 --- a/src/SB/Core/x/xParEmitter.h +++ b/src/SB/Core/x/xParEmitter.h @@ -13,6 +13,8 @@ struct xParInterp U32 interp; F32 freq; F32 oofreq; + + void set(F32, F32, F32, U32); }; // Size 0x138 @@ -106,7 +108,6 @@ void xParEmitterSetup(xParEmitter* t); void xParEmitterDestroy(); void xParEmitterUpdate(xBase* to, xScene*, F32 dt); xPar* xParEmitterEmitCustom(xParEmitter* p, F32 dt, xParEmitterCustomSettings* info); -F32 xParInterpCompute(S32 interp_mode, xParInterp* r, F32 time, S32 time_has_elapsed, - F32 last_val); +F32 xParInterpCompute(S32 interp_mode, xParInterp* r, F32 time, S32 time_has_elapsed, F32 last_val); #endif diff --git a/src/SB/Core/x/xRMemData.cpp b/src/SB/Core/x/xRMemData.cpp index 055ec110..7a748e00 100644 --- a/src/SB/Core/x/xRMemData.cpp +++ b/src/SB/Core/x/xRMemData.cpp @@ -4,9 +4,7 @@ #include #include -#if 0 -// So close to matching. There seems to be extra ors and I do not know why they show up. -void* RyzMemGrow::operator new(size_t size, U32 amt, RyzMemGrow* growCtxt) +void* RyzMemData::operator new(size_t size, S32 amt, RyzMemGrow* growCtxt) { S32 dogrow = true; if (growCtxt == NULL) @@ -17,21 +15,20 @@ void* RyzMemGrow::operator new(size_t size, U32 amt, RyzMemGrow* growCtxt) { dogrow = false; } + + void* mem; if (dogrow) { - xMemGrowAllocSize(size); + mem = xMemGrowAllocSize(size); } else { - xMemAllocSize(size); + mem = xMemAllocSize(size); } - void* mem; memset(mem, 0, 4); return mem; } -#endif - void RyzMemData::operator delete(void* p) { } @@ -73,8 +70,3 @@ void RyzMemGrow::Done() this->user = NULL; this->flg_grow = 0; } - -S32 RyzMemGrow::IsEnabled() -{ - return this->flg_grow & 1; -} diff --git a/src/SB/Core/x/xRMemData.h b/src/SB/Core/x/xRMemData.h index b19398d0..9d0a94be 100644 --- a/src/SB/Core/x/xRMemData.h +++ b/src/SB/Core/x/xRMemData.h @@ -18,7 +18,10 @@ struct RyzMemGrow RyzMemGrow* Init(xBase* growuser); RyzMemGrow* Resume(xBase*); void Done(); - S32 IsEnabled(); + S32 IsEnabled() + { + return this->flg_grow & 1; + } }; struct RyzMemData diff --git a/src/SB/Core/x/xSnd.h b/src/SB/Core/x/xSnd.h index 11314878..f4947662 100644 --- a/src/SB/Core/x/xSnd.h +++ b/src/SB/Core/x/xSnd.h @@ -124,19 +124,18 @@ void xSndInternalUpdateVoicePos(xSndVoiceInfo* voiceInfo); void xSndSetListenerData(sound_listener_type listenerType, const xMat4x3* matrix); void xSndSelectListenerMode(sound_listener_game_mode listenerGameMode); void xSndExit(); -U32 xSndPlay(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, - U32 parentID, sound_category category, F32 delay); -U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, - xEnt* parent, F32 innerRadius, F32 outerRadius, sound_category category, - F32 delay); -U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, - const xVec3* pos, F32 innerRadius, F32 outerRadius, - sound_category category, F32 delay); -U32 xSndPlayInternal(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, - U32 parentID, xEnt* parentEnt, const xVec3* pos, F32 innerRadius, - F32 outerRadius, sound_category category, F32 delay); +U32 xSndPlay(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, + sound_category category, F32 delay); +U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, xEnt* parent, F32 innerRadius, + F32 outerRadius, sound_category category, F32 delay); +U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, const xVec3* pos, + F32 innerRadius, F32 outerRadius, sound_category category, F32 delay); +U32 xSndPlayInternal(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, + xEnt* parentEnt, const xVec3* pos, F32 innerRadius, F32 outerRadius, + sound_category category, F32 delay); void xSndStartStereo(U32 id1, U32 id2, F32 pitch); U8 xSndIsPlayingByHandle(U32 sndID); +U32 xSndIsPlaying(U32 assetID); U32 xSndIDIsPlaying(U32 sndID); void xSndStop(U32 snd); void xSndParentDied(U32 pid); diff --git a/src/SB/Core/x/xUpdateCull.cpp b/src/SB/Core/x/xUpdateCull.cpp index 78c85f45..e69de29b 100644 --- a/src/SB/Core/x/xUpdateCull.cpp +++ b/src/SB/Core/x/xUpdateCull.cpp @@ -1,3 +0,0 @@ -#include "xUpdateCull.h" - -#include diff --git a/src/SB/Game/zAssetTypes.cpp b/src/SB/Game/zAssetTypes.cpp index 7a34644a..44186f3c 100644 --- a/src/SB/Game/zAssetTypes.cpp +++ b/src/SB/Game/zAssetTypes.cpp @@ -6,6 +6,7 @@ #include #include #include +#include extern xJSPHeader* sTempJSP; extern xJSPHeader sDummyEmptyJSP; @@ -67,3 +68,8 @@ void* JSP_Read(void* param_1, U32 param_2, void* indata, U32 insize, U32* outsiz void Anim_Unload(void*, U32) { } + +U8 dummyEffectCB(U32, xAnimActiveEffect*, xAnimSingle*, void*) +{ + return 0; +} diff --git a/src/SB/Game/zEntButton.cpp b/src/SB/Game/zEntButton.cpp index 01f107d8..4dd23219 100644 --- a/src/SB/Game/zEntButton.cpp +++ b/src/SB/Game/zEntButton.cpp @@ -1,3 +1,493 @@ #include "zEntButton.h" +#include "zEntPlayer.h" +#include "zCollGeom.h" +#include "zFX.h" +#include "zShrapnel.h" +#include "zGlobals.h" +#include "xMath.h" +#include "xstransvc.h" +#include "xString.h" #include + +static F32 sRedMultiplier = 1.0f; +static F32 sGreenMultiplier = 1.0f; +static F32 sBlueMultiplier = 1.0f; +static F32 sColorMultiplier = 1.0f; +static S32 sColorMultiplierSign = 1; + +static S32 zEntButtonEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3); + +void zEntButton_Init(void* ent, void* asset) +{ + zEntButton_Init((_zEntButton*)ent, (xEntAsset*)asset); +} + +// Equivalent: scheduling +void zEntButton_Init(_zEntButton* ent, xEntAsset* asset) +{ + zEntInit(ent, asset, 'BUTN'); + + zEntButtonAsset* basset = (zEntButtonAsset*)(asset + 1); + xEntMotionAsset* masset = (xEntMotionAsset*)(basset + 1); + ent->basset = basset; + + U32 size; + RpAtomic* pressed_asset = (RpAtomic*)xSTFindAsset(basset->modelPressedInfoID, &size); + if (pressed_asset != NULL) + { + ent->modelPressed = xEntLoadModel(NULL, pressed_asset); + } + else + { + ent->modelPressed = NULL; + } + + if (asset->modelInfoID == xStrHash("button")) + { + ent->topHeight = 0.36f; + } + else if (asset->modelInfoID == xStrHash("plate_pressure")) + { + ent->topHeight = 0.32524f; + } + else + { + ent->topHeight = 0.0f; + } + + ent->pflags |= (1 << 0); + ent->penby |= XENT_COLLTYPE_PLYR; + ent->chkby |= XENT_COLLTYPE_PLYR; + + ent->update = (xEntUpdateCallback)zEntButton_Update; + ent->move = (xEntMoveCallback)zEntButton_Move; + ent->eventFunc = zEntButtonEventCB; + ent->render = (xEntRenderCallback)zEntButton_Render; + + if (ent->linkCount != 0) + { + ent->link = (xLinkAsset*)(masset + 1); + } + else + { + ent->link = NULL; + } + + // BUG: We've already done this, no need to do it again + ent->eventFunc = zEntButtonEventCB; + + ent->state = 0; + ent->oldState = ent->state; + ent->holdTimer = 0.0f; + ent->counter = ent->basset->resetDelay; + + xEntReset((xEnt*)ent); + xEntMotionInit(&ent->motion, (xEnt*)ent, masset); + xEntMotionRun(&ent->motion); + ent->oldMotState = ent->motion.mech.state; +} + +void zEntButton_Move(_zEntButton* ent, xScene* sc, F32 dt, xEntFrame* frame) +{ + if (ent->driver != NULL) + { + xEntFrame* ent_frame = ent->driver->frame; + if (ent->driveMode == 0) + { + xVec3 diff; + xVec3Sub(&diff, &ent_frame->mat.pos, &ent_frame->oldmat.pos); + xVec3Add(&ent->motion.mech.apos, &ent->motion.mech.apos, &diff); + xVec3Add(&ent->motion.mech.bpos, &ent->motion.mech.bpos, &diff); + } + } + + xEntMotionMove(&ent->motion, sc, dt, frame); +} + +void zEntButton_Setup(_zEntButton* ent, xScene*) +{ + zEntSetup(ent); +} + +void zEntButton_Save(_zEntButton* ent, xSerial* s) +{ + zEntSave(ent, s); + + if (ent->state == 3) + { + s->Write_b1(1); + } + else + { + s->Write_b1(0); + } + + if (ent->state == 1) + { + s->Write_b1(1); + } + else + { + s->Write_b1(0); + } +} + +void zEntButton_Load(_zEntButton* ent, xSerial* s) +{ + zEntLoad(ent, s); + + int unk1 = 0, unk2 = 0; + + s->Read_b1(&unk1); + if (unk1 != 0) + { + ent->state = 1; + } + + s->Read_b1(&unk2); + if (unk2 != 0) + { + ent->state = 1; + } +} + +void zEntButton_Reset(_zEntButton* ent, xScene* sc) +{ + xEntReset((xEnt*)ent); + xEntMotionInit(&ent->motion, (xEnt*)ent, (xEntMotionAsset*)(ent->basset + 1)); + xEntMotionReset(&ent->motion, sc); + + ent->pflags |= (1 << 0); + ent->penby |= XENT_COLLTYPE_PLYR; + if (ent->asset->flags & (1 << 0)) + { + ent->flags |= (1 << 0); + } + ent->chkby |= XENT_COLLTYPE_PLYR; + + ent->bupdate(ent, (xVec3*)&ent->model->Mat->pos); + + ent->state = 0; + + xEntMotionStop(&ent->motion); + ent->oldState = 5; + ent->oldMotState = 6; +} + +void zEntButton_Update(_zEntButton* ent, xScene* sc, F32 dt) +{ + if (ent->modelPressed != NULL) + { + ent->modelPressed->Mat = ent->model->Mat; + } + + xEntUpdate((xEnt*)ent, sc, dt); + + if (ent->motion.mech.state != ent->oldMotState) + { + switch (ent->motion.mech.state) + { + case 0: + if (ent->state == 4) + { + ent->state = 0; + } + break; + case 2: + if (!xEntMotionIsStopped(&ent->motion)) + { + ent->state = 3; + } + break; + case 3: + ent->state = 4; + break; + case 4: + case 5: + case 6: + break; + } + } + ent->oldMotState = ent->motion.mech.state; + + if (ent->state != ent->oldState) + { + switch (ent->state) + { + case 1: + xEntMotionRun(&ent->motion); + break; + case 3: + xEntMotionStop(&ent->motion); + break; + case 4: + xEntMotionRun(&ent->motion); + break; + case 0: + if (ent->motion.mech.state == 0) + { + xEntMotionStop(&ent->motion); + } + if (ent->basset->actMethod == 1) + { + zEntEvent((xBase*)ent, (xBase*)ent, eEventUnpress); + } + break; + } + + ent->oldState = ent->state; + } + + if (ent->basset->actMethod == 0) + { + if (ent->basset->isReset != 0 && ent->state != 0) + { + ent->counter += dt; + } + if (ent->counter > ent->basset->resetDelay && ent->state == 3) + { + zEntEvent((xBase*)ent, (xBase*)ent, eEventUnpress); + } + } + else if (ent->basset->actMethod == 1 && ent->hold == 0) + { + zEntButton_SetReady(ent); + } + + ent->holdTimer -= dt; + if (ent->holdTimer < 0.0f) + { + ent->holdTimer = 0.5f; + ent->hold = 0; + } +} + +void zEntButton_Render(_zEntButton* ent) +{ + xModelInstance* model = ent->model; + + if (ent->state == 3 && ent->modelPressed != NULL) + { + ent->model = ent->modelPressed; + } + else if (ent->basset->actMethod == 0) + { + model->RedMultiplier = sRedMultiplier; + model->GreenMultiplier = sGreenMultiplier; + model->BlueMultiplier = sBlueMultiplier; + } + + if (ent->collType != XENT_COLLTYPE_TRIG) + { + xEntRender((xEnt*)ent); + } + + ent->model = model; +} + +void zEntButton_SetReady(_zEntButton* ent) +{ + if (ent->state != 0) + { + ent->state = 4; + } +} + +void zEntButton_Press(_zEntButton* ent) +{ + xSndPlay3D(xStrHash("Button_press"), 0.77f, 0.0f, 128, 0, (xVec3*)&ent->model->Mat->pos, 10.0f, + 30.0f, SND_CAT_GAME, 0.0f); + + if (ent->state == 0) + { + ent->state = 1; + ent->counter = 0.0f; + } +} + +static void _PressButtonSound(U32 mask) +{ + if (mask & (1 << 3)) + { + zEntPlayer_SNDPlayStreamRandom(0, 16, ePlayerStreamSnd_BowlComment1, + ePlayerStreamSnd_BowlComment3, 0.1f); + zEntPlayer_SNDPlayStreamRandom(16, 35, ePlayerStreamSnd_BowlComment1, + ePlayerStreamSnd_BowlComment4, 0.1f); + zEntPlayer_SNDPlayStreamRandom(36, 100, ePlayerStreamSnd_BowlComment1, + ePlayerStreamSnd_BowlComment5, 0.1f); + } + else if (!(mask & (1 << 11)) && xrand() % 4 == 3) + { + zEntPlayer_SNDPlayStreamRandom(ePlayerStreamSnd_PushButton1, ePlayerStreamSnd_PushButton3, + 0.2f); + } +} + +void zEntButton_Press(_zEntButton* ent, U32 mask) +{ + if (ent->basset->buttonActFlags & mask && ent->state == 0) + { + zEntEvent((xBase*)ent, eEventPress); + _PressButtonSound(mask); + } +} + +void zEntButton_Hold(_zEntButton* ent, U32 mask) +{ + if (!(ent->basset->buttonActFlags & mask)) + { + return; + } + + if (mask & (1 << 10)) + { + switch (ent->bound.type) + { + case XBOUND_TYPE_CYL: + break; + case XBOUND_TYPE_OBB: + xVec3 vec; + xMat4x3Tolocal(&vec, ent->bound.mat, (xVec3*)&globals.player.ent.model->Mat->pos); + vec.y = 0.0f; + if (!xPointInBox(&ent->bound.box.box, &vec)) + { + return; + } + break; + } + } + + if (ent->state == 0) + { + zEntEvent((xBase*)ent, eEventPress); + _PressButtonSound(0); + } + else + { + ent->hold = 1; + } +} + +// Equivalent(?): sda loads, regalloc +void zEntButton_SceneUpdate(F32 dt) +{ + sColorMultiplier += dt * sColorMultiplierSign * 2.5f; + + if (sColorMultiplier > 1.0f) + { + sColorMultiplierSign *= -1; + sColorMultiplier = 1.0f; + } + + if (sColorMultiplier < 0.0f) + { + sColorMultiplierSign *= -1; + sColorMultiplier = 0.0f; + } + + F32 mul = 0.39999999f * sColorMultiplier + 0.6f; + sRedMultiplier = mul; + sGreenMultiplier = mul; + sBlueMultiplier = mul; +} + +static S32 zEntButtonEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3) +{ + _zEntButton* button = (_zEntButton*)to; + + switch (toEvent) + { + case eEventVisible: + case eEventFastVisible: + case eEventCollision_Visible_On: + button->chkby |= XENT_COLLTYPE_PLYR; + xEntShow((xEnt*)button); + button->bupdate((xEnt*)button, (xVec3*)&button->model->Mat->pos); + if (toParam != NULL && (S32)(*toParam + 0.5f) == 77) + { + zFXPopOn((xEnt&)*button, toParam[1], toParam[2]); + } + break; + case eEventInvisible: + case eEventFastInvisible: + case eEventCollision_Visible_Off: + button->chkby &= (U8)~XENT_COLLTYPE_PLYR; + xEntHide((xEnt*)button); + if (toParam != NULL && (S32)(*toParam + 0.5f) == 77) + { + zFXPopOff((xEnt&)*button, toParam[1], toParam[2]); + } + break; + case eEventCameraCollideOn: + zCollGeom_CamEnable((xEnt*)button); + break; + case eEventCameraCollideOff: + zCollGeom_CamDisable((xEnt*)button); + break; + case eEventReset: + zEntButton_Reset(button, globals.sceneCur); + break; + case eEventPress: + zEntButton_Press(button); + break; + case eEventUnpress: + if (button->state == 0) + { + break; + } + + xSndPlay3D(xStrHash("Button_up"), 0.77f, 0.0f, 128, 0, (xVec3*)&button->model->Mat->pos, + 10.0f, 30.0f, SND_CAT_GAME, 0.0f); + zEntButton_SetReady(button); + break; + case eEventToggle: + if (button->state != 0) + { + zEntEvent((xBase*)button, (xBase*)button, eEventUnpress); + } + else + { + zEntEvent((xBase*)button, (xBase*)button, eEventPress); + } + break; + case eEventAnimPlay: + case eEventAnimPlayLoop: + case eEventAnimStop: + case eEventAnimPause: + case eEventAnimResume: + case eEventAnimTogglePause: + case eEventAnimPlayRandom: + case eEventAnimPlayMaybe: + zEntAnimEvent(button, toEvent, toParam); + break; + case eEventSetUpdateDistance: + if (globals.updateMgr == NULL) + { + break; + } + + if (*toParam <= 0.0f) + { + xUpdateCull_SetCB(globals.updateMgr, button, xUpdateCull_AlwaysTrueCB, NULL); + } + else + { + F32 unk = SQR(*toParam); + xUpdateCull_SetCB(globals.updateMgr, button, xUpdateCull_DistanceSquaredCB, + *(void**)&unk); + } + break; + case eEventLaunchShrapnel: + { + zShrapnelAsset* shrapnel = (zShrapnelAsset*)b3; + if (shrapnel != NULL && shrapnel->initCB != NULL) + { + shrapnel->initCB(shrapnel, button->model, NULL, NULL); + } + break; + } + } + + return 1; +} diff --git a/src/SB/Game/zEntButton.h b/src/SB/Game/zEntButton.h index 3c3745e3..db2c5278 100644 --- a/src/SB/Game/zEntButton.h +++ b/src/SB/Game/zEntButton.h @@ -31,11 +31,18 @@ struct _zEntButton : zEnt }; void zEntButton_Init(void* ent, void* asset); +void zEntButton_Init(_zEntButton* ent, xEntAsset* asset); +void zEntButton_Move(_zEntButton* ent, xScene* sc, F32 dt, xEntFrame* frame); void zEntButton_Setup(_zEntButton* ent, xScene* sc); void zEntButton_Save(_zEntButton* ent, xSerial* s); void zEntButton_Load(_zEntButton* ent, xSerial* s); void zEntButton_Reset(_zEntButton* ent, xScene* sc); +void zEntButton_Update(_zEntButton* ent, xScene* sc, F32 dt); +void zEntButton_Render(_zEntButton* ent); +void zEntButton_SetReady(_zEntButton* ent); +void zEntButton_Press(_zEntButton* ent); void zEntButton_Press(_zEntButton* ent, U32 mask); +void zEntButton_Hold(_zEntButton* ent, U32 mask); void zEntButton_SceneUpdate(F32 dt); #endif diff --git a/src/SB/Game/zEntCruiseBubble.cpp b/src/SB/Game/zEntCruiseBubble.cpp index 9ccf3273..d6cb67d5 100644 --- a/src/SB/Game/zEntCruiseBubble.cpp +++ b/src/SB/Game/zEntCruiseBubble.cpp @@ -1245,8 +1245,7 @@ bool cruise_bubble::uv_animated_model::init(RpAtomic* m) return true; } -bool cruise_bubble::uv_animated_model::clone_uv(RwTexCoords*& coords, S32& size, - RpAtomic* m) const +bool cruise_bubble::uv_animated_model::clone_uv(RwTexCoords*& coords, S32& size, RpAtomic* m) const { RwTexCoords* c; if (!this->get_uv(c, size, m)) @@ -1301,9 +1300,9 @@ void cruise_bubble::show_gizmo(hud_gizmo& gizmo, const basic_rect& rect, xM void cruise_bubble::update_gizmo(cruise_bubble::hud_gizmo& gizmo, F32 dt) { gizmo.alpha = range_limit(gizmo.alpha_vel * dt + gizmo.alpha, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0); + zEntCruiseBubble_f_1_0); gizmo.glow = range_limit(gizmo.glow_vel * dt + gizmo.glow, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0); + zEntCruiseBubble_f_1_0); } #ifdef NON_MATCHING @@ -1375,13 +1374,13 @@ void cruise_bubble::update_hud(F32 dt) } hud.alpha = range_limit(hud.alpha_vel * dt + hud.alpha, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0); + zEntCruiseBubble_f_1_0); hud.glow = range_limit(hud.glow_vel * dt + hud.glow, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0); + zEntCruiseBubble_f_1_0); // scheduling off F32 vel_frac = ((state_missle_fly*)shared.states[STATE_MISSLE_FLY])->vel / - current_tweak->missle.fly.max_vel; + current_tweak->missle.fly.max_vel; hud.uv_wind.offset_vel.assign(current_tweak->hud.wind.du, current_tweak->hud.wind.dv); hud.uv_wind.offset_vel *= vel_frac; @@ -1668,8 +1667,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap // scheduling for loading ap and apsize is off :( // stringBase0 + 0x290 == "aim_delay" auto_tweak::load_param(this->aim_delay, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x290); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x290); } if (init) @@ -1677,38 +1676,35 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->player.halt_time = zEntCruiseBubble_f_0_5; // stringBase0 + 0x29a == "player.halt_time" auto_tweak::load_param(this->player.halt_time, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x29a); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x29a); } if (init) { this->player.aim.turn_speed = zEntCruiseBubble_f_0_05; // stringBase0 + 0x2ab == "player.aim.turn_speed" - auto_tweak::load_param(this->player.aim.turn_speed, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x2ab); + auto_tweak::load_param(this->player.aim.turn_speed, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x2ab); } if (init) { this->player.aim.anim_delta = zEntCruiseBubble_f_0_5; // stringBase0 + 0x2c1 == "player.aim.anim_delta" - auto_tweak::load_param(this->player.aim.anim_delta, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x2c1); + auto_tweak::load_param(this->player.aim.anim_delta, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x2c1); } if (init) { this->player.fire.delay_wand = zEntCruiseBubble_f_0_0667; // stringBase0 + 0x2d7 == "player.fire.delay_wand" - auto_tweak::load_param(this->player.fire.delay_wand, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100_0, ap, apsize, - stringBase0 + 0x2d7); + auto_tweak::load_param(this->player.fire.delay_wand, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x2d7); } if (init) @@ -1716,9 +1712,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.life = zEntCruiseBubble_f_6_0; // stringBase0 + 0x2ee == "missle.life" auto_tweak::load_param(this->missle.life, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x2ee); + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x2ee); } if (init) @@ -1726,8 +1721,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.hit_dist = zEntCruiseBubble_f_0_3; // stringBase0 + 0x2fa == "missle.hit_dist" auto_tweak::load_param(this->missle.hit_dist, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x2fa); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x2fa); } if (init) @@ -1735,8 +1730,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.crash_angle = zEntCruiseBubble_f_30_0; // stringBase0 + 0x30a == "missle.crash_angle" auto_tweak::load_param(this->missle.crash_angle, zEntCruiseBubble_f_0_017, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_60_0, - ap, apsize, stringBase0 + 0x30a); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_60_0, ap, + apsize, stringBase0 + 0x30a); } if (init) @@ -1744,8 +1739,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.collide_twist = zEntCruiseBubble_f_0_025; // stringBase0 + 0x31d == "missle.collide_twist" auto_tweak::load_param(this->missle.collide_twist, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x31d); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x31d); } if (init) @@ -1753,27 +1748,25 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.hit_tests = 4; // stringBase0 + 0x332 == "missle.hit_tests" auto_tweak::load_param(this->missle.hit_tests, 1, 1, 100, ap, apsize, - stringBase0 + 0x332); + stringBase0 + 0x332); } if (init) { this->missle.appear.delay_show = zEntCruiseBubble_f_0_1333; // stringBase0 + 0x343 == "missle.appear.delay_show" - auto_tweak::load_param(this->missle.appear.delay_show, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100_0, ap, apsize, - stringBase0 + 0x343); + auto_tweak::load_param(this->missle.appear.delay_show, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x343); } if (init) { this->missle.appear.delay_fly = zEntCruiseBubble_f_0_667; // stringBase0 + 0x35c == "missle.appear.delay_fly" - auto_tweak::load_param(this->missle.appear.delay_fly, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100_0, ap, apsize, - stringBase0 + 0x35c); + auto_tweak::load_param(this->missle.appear.delay_fly, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x35c); } if (init) @@ -1782,7 +1775,7 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap zEntCruiseBubble_f_n0_049, zEntCruiseBubble_f_1_728, zEntCruiseBubble_f_0_922); // stringBase0 + 0x374 == "missle.appear.offset" auto_tweak::load_param(this->missle.appear.offset, 0, 0, 0, ap, apsize, - stringBase0 + 0x374); + stringBase0 + 0x374); } if (init) @@ -1790,9 +1783,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.fly.accel = zEntCruiseBubble_f_6_0; // stringBase0 + 0x389 == "missle.fly.accel" auto_tweak::load_param(this->missle.fly.accel, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x389); + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x389); } if (init) @@ -1800,19 +1792,17 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.fly.max_vel = zEntCruiseBubble_f_12_0; // stringBase0 + 0x39a == "missle.fly.max_vel" auto_tweak::load_param(this->missle.fly.max_vel, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x39a); + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x39a); } if (init) { this->missle.fly.engine_pitch_max = zEntCruiseBubble_f_10_0; // stringBase0 + 0x3ad == "missle.fly.engine_pitch_max" - auto_tweak::load_param(this->missle.fly.engine_pitch_max, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x3ad); + auto_tweak::load_param(this->missle.fly.engine_pitch_max, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x3ad); } if (init) @@ -1820,99 +1810,89 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->missle.fly.engine_pitch_sensitivity = zEntCruiseBubble_f_0_005; // stringBase0 + 0x3c9 == "missle.fly.engine_pitch_sensitivity" auto_tweak::load_param(this->missle.fly.engine_pitch_sensitivity, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x3c9); + zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, + zEntCruiseBubble_f_1_0, ap, apsize, stringBase0 + 0x3c9); } if (init) { this->missle.fly.flash_interval = zEntCruiseBubble_f_2_0; // stringBase0 + 0x3ed == "missle.fly.flash_interval" - auto_tweak::load_param(this->missle.fly.flash_interval, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x3ed); + auto_tweak::load_param(this->missle.fly.flash_interval, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x3ed); } if (init) { this->missle.fly.turn.xdelta = zEntCruiseBubble_f_5_0; // stringBase0 + 0x407 == "missle.fly.turn.xdelta" - auto_tweak::load_param(this->missle.fly.turn.xdelta, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x407); + auto_tweak::load_param(this->missle.fly.turn.xdelta, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x407); } if (init) { this->missle.fly.turn.ydelta = zEntCruiseBubble_f_4_0; // stringBase0 + 0x41e == "missle.fly.turn.ydelta" - auto_tweak::load_param(this->missle.fly.turn.ydelta, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x41e); + auto_tweak::load_param(this->missle.fly.turn.ydelta, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x41e); } if (init) { this->missle.fly.turn.xdecay = zEntCruiseBubble_f_0_99; // stringBase0 + 0x435 == "missle.fly.turn.xdecay" - auto_tweak::load_param(this->missle.fly.turn.xdecay, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x435); + auto_tweak::load_param(this->missle.fly.turn.xdecay, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x435); } if (init) { this->missle.fly.turn.ydecay = zEntCruiseBubble_f_0_99; // stringBase0 + 0x44c == "missle.fly.turn.ydecay" - auto_tweak::load_param(this->missle.fly.turn.ydecay, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x44c); + auto_tweak::load_param(this->missle.fly.turn.ydecay, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x44c); } if (init) { this->missle.fly.turn.ybound = zEntCruiseBubble_f_0_6; // stringBase0 + 0x463 == "missle.fly.turn.ybound" - auto_tweak::load_param(this->missle.fly.turn.ybound, - zEntCruiseBubble_f_1_5708, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x463); + auto_tweak::load_param(this->missle.fly.turn.ybound, zEntCruiseBubble_f_1_5708, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x463); } if (init) { this->missle.fly.turn.roll_frac = zEntCruiseBubble_f_0_2; // stringBase0 + 0x47a == "missle.fly.turn.roll_frac" - auto_tweak::load_param(this->missle.fly.turn.roll_frac, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_n1_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x47a); + auto_tweak::load_param(this->missle.fly.turn.roll_frac, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_n1_0, zEntCruiseBubble_f_1_0, ap, + apsize, stringBase0 + 0x47a); } if (init) { this->missle.explode.hit_radius = zEntCruiseBubble_f_1_0; // stringBase0 + 0x494 == "missle.explode.hit_radius" - auto_tweak::load_param(this->missle.explode.hit_radius, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x494); + auto_tweak::load_param(this->missle.explode.hit_radius, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x494); } if (init) { this->missle.explode.hit_duration = zEntCruiseBubble_f_0_25; // stringBase0 + 0x4ae == "missle.explode.hit_duration" - auto_tweak::load_param(this->missle.explode.hit_duration, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x4ae); + auto_tweak::load_param(this->missle.explode.hit_duration, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x4ae); } if (init) @@ -1920,8 +1900,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->camera.aim.dist = zEntCruiseBubble_f_2_0; // stringBase0 + 0x4ca == "camera.aim.dist" auto_tweak::load_param(this->camera.aim.dist, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, - ap, apsize, stringBase0 + 0x4ca); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x4ca); } if (init) @@ -1929,8 +1909,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->camera.aim.height = zEntCruiseBubble_f_1_5; // stringBase0 + 0x4da == "camera.aim.height" auto_tweak::load_param(this->camera.aim.height, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_n10_0, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x4da); + zEntCruiseBubble_f_n10_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x4da); } if (init) @@ -1938,8 +1918,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->camera.aim.pitch = zEntCruiseBubble_f_0_0; // stringBase0 + 0x4ec == "camera.aim.pitch" auto_tweak::load_param(this->camera.aim.pitch, zEntCruiseBubble_f_0_017, - zEntCruiseBubble_f_n90_0, zEntCruiseBubble_f_90_0, - ap, apsize, stringBase0 + 0x4ec); + zEntCruiseBubble_f_n90_0, zEntCruiseBubble_f_90_0, ap, + apsize, stringBase0 + 0x4ec); } if (init) @@ -1947,9 +1927,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->camera.aim.accel = zEntCruiseBubble_f_10_0; // stringBase0 + 0x4fd == "camera.aim.accel" auto_tweak::load_param(this->camera.aim.accel, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x4fd); + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x4fd); } if (init) @@ -1957,49 +1936,44 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->camera.aim.max_vel = zEntCruiseBubble_f_5_0; // stringBase0 + 0x50e == "camera.aim.max_vel" auto_tweak::load_param(this->camera.aim.max_vel, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x50e); + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x50e); } if (init) { this->camera.aim.stick_decel = zEntCruiseBubble_f_720_0; // stringBase0 + 0x521 == "camera.aim.stick_decel" - auto_tweak::load_param(this->camera.aim.stick_decel, - zEntCruiseBubble_f_0_017, zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x521); + auto_tweak::load_param(this->camera.aim.stick_decel, zEntCruiseBubble_f_0_017, + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x521); } if (init) { this->camera.aim.stick_accel = zEntCruiseBubble_f_360_0; // stringBase0 + 0x538 == "camera.aim.stick_accel" - auto_tweak::load_param(this->camera.aim.stick_accel, - zEntCruiseBubble_f_0_017, zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x538); + auto_tweak::load_param(this->camera.aim.stick_accel, zEntCruiseBubble_f_0_017, + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x538); } if (init) { this->camera.aim.stick_max_vel = zEntCruiseBubble_f_135_0; // stringBase0 + 0x54f == "camera.aim.stick_max_vel" - auto_tweak::load_param(this->camera.aim.stick_max_vel, - zEntCruiseBubble_f_0_017, zEntCruiseBubble_f_0_01, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x54f); + auto_tweak::load_param(this->camera.aim.stick_max_vel, zEntCruiseBubble_f_0_017, + zEntCruiseBubble_f_0_01, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x54f); } if (init) { this->camera.aim.turn_speed = zEntCruiseBubble_f_0_2; // stringBase0 + 0x568 == "camera.aim.turn_speed" - auto_tweak::load_param(this->camera.aim.turn_speed, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_001, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x568); + auto_tweak::load_param(this->camera.aim.turn_speed, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x568); } if (init) @@ -2007,39 +1981,35 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->camera.seize.delay = zEntCruiseBubble_f_0_0; // stringBase0 + 0x57e == "camera.seize.delay" auto_tweak::load_param(this->camera.seize.delay, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x57e); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x57e); } if (init) { this->camera.seize.blend_time = zEntCruiseBubble_f_1_5; // stringBase0 + 0x591 == "camera.seize.blend_time" - auto_tweak::load_param(this->camera.seize.blend_time, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x591); + auto_tweak::load_param(this->camera.seize.blend_time, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1000000000_0, + ap, apsize, stringBase0 + 0x591); } if (init) { this->camera.seize.fade_dist = zEntCruiseBubble_f_2_0; // stringBase0 + 0x5a9 == "camera.seize.fade_dist" - auto_tweak::load_param(this->camera.seize.fade_dist, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x5a9); + auto_tweak::load_param(this->camera.seize.fade_dist, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x5a9); } if (init) { this->camera.seize.hide_dist = zEntCruiseBubble_f_1_0; // stringBase0 + 0x5c0 == "camera.seize.hide_dist" - auto_tweak::load_param(this->camera.seize.hide_dist, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x5c0); + auto_tweak::load_param(this->camera.seize.hide_dist, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x5c0); } if (init) @@ -2047,98 +2017,89 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->camera.seize.fov = zEntCruiseBubble_f_95_0; // stringBase0 + 0x5d7 == "camera.seize.fov" auto_tweak::load_param(this->camera.seize.fov, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_10_0, zEntCruiseBubble_f_180_0, - ap, apsize, stringBase0 + 0x5d7); + zEntCruiseBubble_f_10_0, zEntCruiseBubble_f_180_0, ap, + apsize, stringBase0 + 0x5d7); } if (init) { this->camera.survey.duration = zEntCruiseBubble_f_2_0; // stringBase0 + 0x5e8 == "camera.survey.duration" - auto_tweak::load_param(this->camera.survey.duration, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x5e8); + auto_tweak::load_param(this->camera.survey.duration, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x5e8); } if (init) { this->camera.survey.min_duration = zEntCruiseBubble_f_0_25; // stringBase0 + 0x5ff == "camera.survey.min_duration" - auto_tweak::load_param(this->camera.survey.min_duration, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x5ff); + auto_tweak::load_param(this->camera.survey.min_duration, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x5ff); } if (init) { this->camera.survey.min_dist = zEntCruiseBubble_f_10_0; // stringBase0 + 0x61a == "camera.survey.min_dist" - auto_tweak::load_param(this->camera.survey.min_dist, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100_0, ap, apsize, - stringBase0 + 0x61a); + auto_tweak::load_param(this->camera.survey.min_dist, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x61a); } if (init) { this->camera.survey.cut_dist = zEntCruiseBubble_f_6_0; // stringBase0 + 0x631 == "camera.survey.cut_dist" - auto_tweak::load_param(this->camera.survey.cut_dist, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100_0, ap, apsize, - stringBase0 + 0x631); + auto_tweak::load_param(this->camera.survey.cut_dist, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x631); } if (init) { this->camera.survey.drift_dist = zEntCruiseBubble_f_8_0; // stringBase0 + 0x648 == "camera.survey.drift_dist" - auto_tweak::load_param(this->camera.survey.drift_dist, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100_0, ap, apsize, - stringBase0 + 0x648); + auto_tweak::load_param(this->camera.survey.drift_dist, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x648); } if (init) { this->camera.survey.drift_softness = zEntCruiseBubble_f_0_1; // stringBase0 + 0x661 == "camera.survey.drift_softness" - auto_tweak::load_param(this->camera.survey.drift_softness, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_0_5, ap, apsize, - stringBase0 + 0x661); + auto_tweak::load_param(this->camera.survey.drift_softness, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_0_5, ap, apsize, + stringBase0 + 0x661); } if (init) { this->camera.survey.jerk_offset = zEntCruiseBubble_f_0_8; // stringBase0 + 0x67e == "camera.survey.jerk_offset" - auto_tweak::load_param(this->camera.survey.jerk_offset, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_2_0, ap, apsize, - stringBase0 + 0x67e); + auto_tweak::load_param(this->camera.survey.jerk_offset, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_2_0, ap, apsize, + stringBase0 + 0x67e); } if (init) { this->camera.survey.jerk_deflect = zEntCruiseBubble_f_0_6; // stringBase0 + 0x698 == "camera.survey.jerk_deflect" - auto_tweak::load_param(this->camera.survey.jerk_deflect, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x698); + auto_tweak::load_param(this->camera.survey.jerk_deflect, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x698); } if (init) { this->camera.restore.control_delay = zEntCruiseBubble_f_0_25; // stringBase0 + 0x6b3 == "camera.restore.control_delay" - auto_tweak::load_param(this->camera.restore.control_delay, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x6b3); + auto_tweak::load_param(this->camera.restore.control_delay, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x6b3); } if (init) @@ -2146,8 +2107,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->material.env_alpha = zEntCruiseBubble_f_0_5; // stringBase0 + 0x6d0 == "material.env_alpha" auto_tweak::load_param(this->material.env_alpha, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x6d0); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x6d0); } if (init) @@ -2155,28 +2116,26 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->material.env_coeff = zEntCruiseBubble_f_0_5; // stringBase0 + 0x6e3 == "material.env_coeff" auto_tweak::load_param(this->material.env_coeff, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x6e3); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x6e3); } if (init) { this->material.fresnel_alpha = zEntCruiseBubble_f_0_0; // stringBase0 + 0x6f6 == "material.fresnel_alpha" - auto_tweak::load_param(this->material.fresnel_alpha, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x6f6); + auto_tweak::load_param(this->material.fresnel_alpha, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x6f6); } if (init) { this->material.fresnel_coeff = zEntCruiseBubble_f_0_75; // stringBase0 + 0x70d == "material.fresnel_coeff" - auto_tweak::load_param(this->material.fresnel_coeff, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x70d); + auto_tweak::load_param(this->material.fresnel_coeff, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x70d); } if (init) @@ -2184,8 +2143,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->reticle.dist_min = zEntCruiseBubble_f_3_0; // stringBase0 + 0x724 == "reticle.dist_min" auto_tweak::load_param(this->reticle.dist_min, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x724); + zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x724); } if (init) @@ -2193,8 +2152,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->reticle.dist_max = zEntCruiseBubble_f_30_0; // stringBase0 + 0x735 == "reticle.dist_max" auto_tweak::load_param(this->reticle.dist_max, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_10000_0, - ap, apsize, stringBase0 + 0x735); + zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_10000_0, ap, + apsize, stringBase0 + 0x735); } if (init) @@ -2202,8 +2161,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->reticle.ang_show = zEntCruiseBubble_f_4_0; // stringBase0 + 0x746 == "reticle.ang_show" auto_tweak::load_param(this->reticle.ang_show, zEntCruiseBubble_f_0_017, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_90_0, - ap, apsize, stringBase0 + 0x746); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_90_0, ap, + apsize, stringBase0 + 0x746); } if (init) @@ -2211,18 +2170,17 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->reticle.ang_hide = zEntCruiseBubble_f_22_5; // stringBase0 + 0x757 == "reticle.ang_hide" auto_tweak::load_param(this->reticle.ang_hide, zEntCruiseBubble_f_0_017, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_90_0, - ap, apsize, stringBase0 + 0x757); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_90_0, ap, + apsize, stringBase0 + 0x757); } if (init) { this->reticle.delay_retarget = zEntCruiseBubble_f_0_25; // stringBase0 + 0x768 == "reticle.delay_retarget" - auto_tweak::load_param(this->reticle.delay_retarget, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_5_0, ap, apsize, - stringBase0 + 0x768); + auto_tweak::load_param(this->reticle.delay_retarget, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_5_0, ap, apsize, + stringBase0 + 0x768); } if (init) @@ -2230,8 +2188,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->trail.sample_rate = zEntCruiseBubble_f_60_0; // stringBase0 + 0x77f == "trail.sample_rate" auto_tweak::load_param(this->trail.sample_rate, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10000_0, - ap, apsize, stringBase0 + 0x77f); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10000_0, ap, + apsize, stringBase0 + 0x77f); } if (init) @@ -2239,28 +2197,26 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->trail.bubble_rate = zEntCruiseBubble_f_60_0; // stringBase0 + 0x791 == "trail.bubble_rate" auto_tweak::load_param(this->trail.bubble_rate, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10000_0, - ap, apsize, stringBase0 + 0x791); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10000_0, ap, + apsize, stringBase0 + 0x791); } if (init) { this->trail.bubble_emit_radius = zEntCruiseBubble_f_0_5; // stringBase0 + 0x7a3 == "trail.bubble_emit_radius" - auto_tweak::load_param(this->trail.bubble_emit_radius, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x7a3); + auto_tweak::load_param(this->trail.bubble_emit_radius, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x7a3); } if (init) { this->trail.wake_emit_radius = zEntCruiseBubble_f_0_1; // stringBase0 + 0x7bc == "trail.wake_emit_radius" - auto_tweak::load_param(this->trail.wake_emit_radius, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_10_0, ap, apsize, - stringBase0 + 0x7bc); + auto_tweak::load_param(this->trail.wake_emit_radius, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x7bc); } if (init) @@ -2268,7 +2224,7 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->blast.emit = 300; // stringBase0 + 0x7d3 == "blast.emit" auto_tweak::load_param(this->blast.emit, 1, 0, 0x3e8, ap, apsize, - stringBase0 + 0x7d3); + stringBase0 + 0x7d3); } if (init) @@ -2276,8 +2232,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->blast.radius = zEntCruiseBubble_f_0_0; // stringBase0 + 0x7de == "blast.radius" auto_tweak::load_param(this->blast.radius, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x7de); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x7de); } if (init) @@ -2285,9 +2241,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->blast.vel = zEntCruiseBubble_f_5_0; // stringBase0 + 0x7eb == "blast.vel" auto_tweak::load_param(this->blast.vel, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_n100000_0, - zEntCruiseBubble_f_100000_0, ap, apsize, - stringBase0 + 0x7eb); + zEntCruiseBubble_f_n100000_0, zEntCruiseBubble_f_100000_0, + ap, apsize, stringBase0 + 0x7eb); } if (init) @@ -2295,9 +2250,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->blast.rand_vel = zEntCruiseBubble_f_0_5; // stringBase0 + 0x7f5 == "blast.rand_vel" auto_tweak::load_param(this->blast.rand_vel, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_n100000_0, - zEntCruiseBubble_f_100000_0, ap, apsize, - stringBase0 + 0x7f5); + zEntCruiseBubble_f_n100000_0, zEntCruiseBubble_f_100000_0, + ap, apsize, stringBase0 + 0x7f5); } if (init) @@ -2305,8 +2259,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.dist_min = zEntCruiseBubble_f_1_0; // stringBase0 + 0x804 == "droplet.dist_min" auto_tweak::load_param(this->droplet.dist_min, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x804); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x804); } if (init) @@ -2314,8 +2268,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.dist_max = zEntCruiseBubble_f_2_0; // stringBase0 + 0x815 == "droplet.dist_max" auto_tweak::load_param(this->droplet.dist_max, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x815); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x815); } if (init) @@ -2323,7 +2277,7 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.emit_min = 10; // stringBase0 + 0x826 == "droplet.emit_min" auto_tweak::load_param(this->droplet.emit_min, 1, 0, 0x1e, ap, apsize, - stringBase0 + 0x826); + stringBase0 + 0x826); } if (init) @@ -2331,7 +2285,7 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.emit_max = 20; // stringBase0 + 0x837 == "droplet.emit_max" auto_tweak::load_param(this->droplet.emit_max, 1, 0, 0x1e, ap, apsize, - stringBase0 + 0x837); + stringBase0 + 0x837); } if (init) @@ -2339,9 +2293,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.vel_min = zEntCruiseBubble_f_2_0; // stringBase0 + 0x848 == "droplet.vel_min" auto_tweak::load_param(this->droplet.vel_min, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100000_0, ap, apsize, - stringBase0 + 0x848); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100000_0, ap, + apsize, stringBase0 + 0x848); } if (init) @@ -2349,9 +2302,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.vel_max = zEntCruiseBubble_f_6_0; // stringBase0 + 0x858 == "droplet.vel_max" auto_tweak::load_param(this->droplet.vel_max, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100000_0, ap, apsize, - stringBase0 + 0x858); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100000_0, ap, + apsize, stringBase0 + 0x858); } if (init) @@ -2359,9 +2311,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.vel_perturb = zEntCruiseBubble_f_0_25; // stringBase0 + 0x868 == "droplet.vel_perturb" auto_tweak::load_param(this->droplet.vel_perturb, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100000_0, ap, apsize, - stringBase0 + 0x868); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100000_0, ap, + apsize, stringBase0 + 0x868); } if (init) @@ -2369,19 +2320,17 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->droplet.vel_angle = zEntCruiseBubble_f_60_0; // stringBase0 + 0x87c == "droplet.vel_angle" auto_tweak::load_param(this->droplet.vel_angle, zEntCruiseBubble_f_0_017, - zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100000_0, ap, apsize, - stringBase0 + 0x87c); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100000_0, ap, + apsize, stringBase0 + 0x87c); } if (init) { this->droplet.rot_vel_max = zEntCruiseBubble_f_360_0; // stringBase0 + 0x88e == "droplet.rot_vel_max" - auto_tweak::load_param(this->droplet.rot_vel_max, - zEntCruiseBubble_f_0_017, zEntCruiseBubble_f_0_0, - zEntCruiseBubble_f_100000_0, ap, apsize, - stringBase0 + 0x88e); + auto_tweak::load_param(this->droplet.rot_vel_max, zEntCruiseBubble_f_0_017, + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100000_0, ap, + apsize, stringBase0 + 0x88e); } if (init) @@ -2389,8 +2338,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.glow_size = zEntCruiseBubble_f_0_05; // stringBase0 + 0x8a2 == "hud.glow_size" auto_tweak::load_param(this->hud.glow_size, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x8a2); + zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x8a2); } if (init) @@ -2398,8 +2347,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.time_fade = zEntCruiseBubble_f_0_25; // stringBase0 + 0x8b0 == "hud.time_fade" auto_tweak::load_param(this->hud.time_fade, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x8b0); + zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x8b0); } if (init) @@ -2407,8 +2356,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.time_glow = zEntCruiseBubble_f_0_5; // stringBase0 + 0x8be == "hud.time_glow" auto_tweak::load_param(this->hud.time_glow, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x8be); + zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x8be); } if (init) @@ -2416,8 +2365,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.wind.size = zEntCruiseBubble_f_0_75; // stringBase0 + 0x8cc == "hud.wind.size" auto_tweak::load_param(this->hud.wind.size, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, - ap, apsize, stringBase0 + 0x8cc); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x8cc); } if (init) @@ -2425,9 +2374,9 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.wind.du = zEntCruiseBubble_f_0_0; // stringBase0 + 0x8da == "hud.wind.du" auto_tweak::load_param(this->hud.wind.du, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_n1000000000_0, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x8da); + zEntCruiseBubble_f_n1000000000_0, + zEntCruiseBubble_f_1000000000_0, ap, apsize, + stringBase0 + 0x8da); } if (init) @@ -2435,9 +2384,9 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.wind.dv = zEntCruiseBubble_f_4_0; // stringBase0 + 0x8e6 == "hud.wind.dv" auto_tweak::load_param(this->hud.wind.dv, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_n1000000000_0, - zEntCruiseBubble_f_1000000000_0, ap, apsize, - stringBase0 + 0x8e6); + zEntCruiseBubble_f_n1000000000_0, + zEntCruiseBubble_f_1000000000_0, ap, apsize, + stringBase0 + 0x8e6); } if (init) @@ -2445,8 +2394,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.reticle.size = zEntCruiseBubble_f_0_1; // stringBase0 + 0x8f2 == "hud.reticle.size" auto_tweak::load_param(this->hud.reticle.size, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, - ap, apsize, stringBase0 + 0x8f2); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x8f2); } if (init) @@ -2454,8 +2403,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.target.size = zEntCruiseBubble_f_0_1; // stringBase0 + 0x903 == "hud.target.size" auto_tweak::load_param(this->hud.target.size, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, - ap, apsize, stringBase0 + 0x903); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_100_0, ap, + apsize, stringBase0 + 0x903); } if (init) @@ -2463,7 +2412,7 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.timer.font = 2; // stringBase0 + 0x913 == "hud.timer.font" auto_tweak::load_param(this->hud.timer.font, 1, 0, 4, ap, apsize, - stringBase0 + 0x913); + stringBase0 + 0x913); } if (init) @@ -2471,18 +2420,17 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.timer.font_width = zEntCruiseBubble_f_0_0275; // stringBase0 + 0x922 == "hud.timer.font_width" auto_tweak::load_param(this->hud.timer.font_width, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_1_0, - ap, apsize, stringBase0 + 0x922); + zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_1_0, ap, + apsize, stringBase0 + 0x922); } if (init) { this->hud.timer.font_height = zEntCruiseBubble_f_0_047; // stringBase0 + 0x937 == "hud.timer.font_height" - auto_tweak::load_param(this->hud.timer.font_height, - zEntCruiseBubble_f_1_0, zEntCruiseBubble_f_0_001, - zEntCruiseBubble_f_1_0, ap, apsize, - stringBase0 + 0x937); + auto_tweak::load_param(this->hud.timer.font_height, zEntCruiseBubble_f_1_0, + zEntCruiseBubble_f_0_001, zEntCruiseBubble_f_1_0, ap, + apsize, stringBase0 + 0x937); } if (init) @@ -2490,8 +2438,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.timer.x = zEntCruiseBubble_f_0_78; // stringBase0 + 0x94d == "hud.timer.x" auto_tweak::load_param(this->hud.timer.x, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x94d); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x94d); } if (init) @@ -2499,8 +2447,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.timer.y = zEntCruiseBubble_f_0_86; // stringBase0 + 0x959 == "hud.timer.y" auto_tweak::load_param(this->hud.timer.y, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x959); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x959); } if (init) @@ -2508,8 +2456,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->hud.timer.glow_size = zEntCruiseBubble_f_0_01; // stringBase0 + 0x965 == "hud.timer.glow_size" auto_tweak::load_param(this->hud.timer.glow_size, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, - ap, apsize, stringBase0 + 0x965); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_10_0, ap, + apsize, stringBase0 + 0x965); } if (init) @@ -2517,8 +2465,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->dialog.freq = zEntCruiseBubble_f_1_0; // stringBase0 + 0x979 == "dialog.freq" auto_tweak::load_param(this->dialog.freq, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x979); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x979); } if (init) @@ -2526,8 +2474,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->dialog.decay = zEntCruiseBubble_f_0_75; // stringBase0 + 0x985 == "dialog.decay" auto_tweak::load_param(this->dialog.decay, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x985); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x985); } if (init) @@ -2535,8 +2483,8 @@ void cruise_bubble::tweak_group::register_tweaks(bool init, xModelAssetParam* ap this->dialog.min_freq = zEntCruiseBubble_f_0_1; // stringBase0 + 0x992 == "dialog.min_freq" auto_tweak::load_param(this->dialog.min_freq, zEntCruiseBubble_f_1_0, - zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, - apsize, stringBase0 + 0x992); + zEntCruiseBubble_f_0_0, zEntCruiseBubble_f_1_0, ap, apsize, + stringBase0 + 0x992); } if (init) @@ -2986,7 +2934,7 @@ cruise_bubble::state_enum cruise_bubble::state_player_aim::update(F32 dt) void cruise_bubble::state_player_aim::update_animation(F32 dt) { F32 r = range_limit(this->yaw_vel * current_tweak->player.aim.anim_delta, - zEntCruiseBubble_f_n1_0, zEntCruiseBubble_f_1_0); + zEntCruiseBubble_f_n1_0, zEntCruiseBubble_f_1_0); xAnimSingle* s = globals.player.ent.model->Anim->Single; s->BilinearLerp[0] = zEntCruiseBubble_f_0_5 * ((zEntCruiseBubble_f_1_0 + s->BilinearLerp[0]) + r); @@ -3417,7 +3365,7 @@ U8 cruise_bubble::state_missle_fly::collide() #ifdef NON_MATCHING U8 cruise_bubble::state_missle_fly::hit_test(xVec3& hit_loc, xVec3& hit_norm, xVec3& hit_depen, - xEnt*& hit_ent) const + xEnt*& hit_ent) const { xScene* s = globals.sceneCur; xVec3* loc = &get_missle_mat()->pos; @@ -3471,8 +3419,7 @@ void cruise_bubble::state_missle_explode::start() F32 dist = (shared.hit_loc - get_player_loc()).length2(); // regalloc for current_tweak - F32 min_dist = - current_tweak->camera.survey.min_dist * current_tweak->camera.survey.min_dist; + F32 min_dist = current_tweak->camera.survey.min_dist * current_tweak->camera.survey.min_dist; // scheduling for THREAD_CAMERA set_state(THREAD_CAMERA, dist <= min_dist ? STATE_CAMERA_RESTORE : STATE_CAMERA_SURVEY); @@ -3770,3 +3717,8 @@ void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) o->y = y; o->z = z; } + +S32 zNPCCommon::IsHealthy() +{ + return 1; +} diff --git a/src/SB/Game/zEntPlayer.cpp b/src/SB/Game/zEntPlayer.cpp index 09b99cc3..f173e32f 100644 --- a/src/SB/Game/zEntPlayer.cpp +++ b/src/SB/Game/zEntPlayer.cpp @@ -1,8 +1,10 @@ +#include "zFX.h" #include #include #include #include +#include "iAnim.h" #include "iMath.h" #include "iSnd.h" @@ -10,6 +12,7 @@ #include "xEnt.h" #include "xEntBoulder.h" #include "xEvent.h" +#include "xJaw.h" #include "xMath.h" #include "xMathInlines.h" #include "xMemMgr.h" @@ -22,6 +25,8 @@ #include "zBase.h" #include "zCamera.h" +#include "zEntButton.h" +#include "zEntDestructObj.h" #include "zEntPlayer.h" #include "zEntPlayerOOBState.h" #include "zEntTeleportBox.h" @@ -35,6 +40,7 @@ #include "zNPCTypeTiki.h" #include "zNPCMessenger.h" #include "zParPTank.h" +#include "zPlatform.h" #include "zRumble.h" #include "zSaveLoad.h" #include "zSurface.h" @@ -69,7 +75,7 @@ static S32 sPlayerAttackInAir; #define MAX_DELAYED_SOUNDS 8 static zDelayedStreamSound sDelayedSound[MAX_DELAYED_SOUNDS]; -static zPlayerSndTimer sPlayerStreamSndTimer[ePlayerStreamSnd_Total]; +static zPlayerSndTimer sPlayerStreamSndTimer[ePlayerStreamSnd_Total] = {}; F32 startJump; F32 startDouble; @@ -119,6 +125,18 @@ xEntBoulder* boulderVehicle; static F32 bvTimeToIdle; static S32 boulderRollShouldEnd; static S32 boulderRollShouldStart; +static zParEmitter* sEmitSpinBubbles; +static zParEmitter* sEmitSundae; +static zParEmitter* sEmitStankBreath; +static class xModelTag sStankTag[3]; + +static RpAtomic* sReticleModel; +static F32 sReticleRot; +static F32 sReticleAlpha; +static xMat4x3 sReticleMat; +static S32 sTypeOfTarget; +static F32 sTimeToRetarget; +class xEnt* gReticleTarget; // This struct was anonymous in the dwarf but it seemed to do better with codegen to name it // so I can hold a pointer to it and access the members that way. @@ -2378,6 +2396,682 @@ static U32 BoulderRollMoveCheck(xAnimTransition*, xAnimSingle*, void*) return bvTimeToIdle > 0.0f && boulderVehicle; } +static U32 BoulderRollIdleCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return bvTimeToIdle <= 0.0f && boulderVehicle; +} + +static U32 BoulderRollCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return boulderRollShouldStart && boulderVehicle; +} + +static U32 BoulderRollWindupCB(xAnimTransition*, xAnimSingle*, void*) +{ + zEntPlayer_SNDPlay(ePlayerSnd_BoulderStart, 0.0f); + zEntPlayer_SNDPlayStreamRandom(ePlayerStreamSnd_SpongeBallComment1, + ePlayerStreamSnd_SpongeBallComment3, 0.2f); + zEntPlayer_SNDStop(ePlayerSnd_SlipLoop); + return 0; +} + +static void zEntPlayer_BoulderVehicleUpdate(xEnt* ent, xScene* sc, F32 dt); +static void zEntPlayer_BoulderVehicleMove(xEnt*, xScene*, F32, xEntFrame* frame); +static void zEntPlayer_BoulderVehicleRender(xEnt*); + +static U32 BoulderRollCB(xAnimTransition*, xAnimSingle*, void*) +{ + xEntHide(&globals.player.ent); + xEntBoulder_Reset(boulderVehicle, globals.sceneCur); + xVec3Copy((xVec3*)&boulderVehicle->model->Mat->pos, + (xVec3*)&globals.player.ent.model->Mat->pos); + + boulderVehicle->model->Mat->pos.y += boulderVehicle->bound.sph.r; + xVec3SubFrom((xVec3*)&boulderVehicle->model->Mat->pos, + (xVec3*)&boulderVehicle->model->Data->boundingSphere.center); + + globals.player.ent.update = zEntPlayer_BoulderVehicleUpdate; + globals.player.ent.move = zEntPlayer_BoulderVehicleMove; + globals.player.ent.render = zEntPlayer_BoulderVehicleRender; + boulderVehicle->vel.y = 0.0f; + boulderVehicle->vel.x = globals.player.PredictCurrDir.x * globals.player.PredictCurrVel; + boulderVehicle->vel.z = globals.player.PredictCurrDir.z * globals.player.PredictCurrVel; + boulderVehicle->rotVec.x = boulderVehicle->vel.z; + boulderVehicle->rotVec.y = 0.0f; + boulderVehicle->rotVec.z = -boulderVehicle->vel.x; + + xVec3Normalize(&boulderVehicle->rotVec, &boulderVehicle->rotVec); + boulderVehicle->angVel = xVec3Length(&boulderVehicle->vel) / boulderVehicle->bound.sph.r; + + xVec3Copy((xVec3*)&boulderVehicle->model->Mat->right, + (xVec3*)&globals.player.ent.model->Mat->right); + xVec3Copy((xVec3*)&boulderVehicle->model->Mat->at, (xVec3*)&globals.player.ent.model->Mat->at); + xVec3Copy((xVec3*)&boulderVehicle->model->Mat->up, (xVec3*)&globals.player.ent.model->Mat->up); + + xParEmitterCustomSettings info; + if (gPTankDisable) + { + info.custom_flags = 0x35e; + xVec3Copy(&info.pos, (xVec3*)&boulderVehicle->model->Mat->pos); + xVec3Copy(&info.vel, (xVec3*)&boulderVehicle->vel); + + if (xVec3Normalize(&info.vel, &info.vel) < 0.00001f) + { + info.vel.x = 0.0f; + info.vel.y = 3.0f; + info.vel.z = 0.0f; + } + else + { + xVec3SMulBy(&info.vel, 3.0f); + } + + info.vel_angle_variation = DEG2RAD(270); + info.rate.set(3000.0f, 3000.0f, 1.0f, 0.0f); + info.life.set(0.75f, 0.75f, 1.0f, 0.0f); + info.size_birth.set(0.25f, 0.25f, 1.0f, 0.0f); + info.size_death.set(0.5f, 0.5f, 1.0f, 0.0f); + + xParEmitterEmitCustom(sEmitSpinBubbles, update_dt, &info); + xVec3AddScaled(&info.pos, &boulderVehicle->vel, 10.0f * update_dt); + xParEmitterEmitCustom(sEmitSpinBubbles, update_dt, &info); + } + else + { + zFX_SpawnBubbleHit((xVec3*)&boulderVehicle->model->Mat->pos, 50); + } + + boulderRollShouldEnd = 0; + zEntEvent(&globals.player.ent, eEventSpongeballOn); + xEntBeginUpdate(boulderVehicle, globals.sceneCur, 0.00001f); + xEntEndUpdate(boulderVehicle, globals.sceneCur, 0.00001f); + xEntBoulder_RealBUpdate(boulderVehicle, &boulderVehicle->frame->mat.pos); + boulderVehicle->lightKit = globals.player.ent.lightKit; + boulderVehicle->model->LightKit = globals.player.ent.lightKit; + + return 0; +} + +static U32 BoulderRollDoneCheck() +{ + if (globals.sceneCur->sceneID == 'PG12') + { + return 0; + } + + return !globals.player.ControlOff && + (globals.pad0->pressed & + (XPAD_BUTTON_TRIANGLE | XPAD_BUTTON_SQUARE | XPAD_BUTTON_O | XPAD_BUTTON_X)) || + boulderRollShouldEnd; +} + +static void zEntPlayer_Update(xEnt* ent, xScene* sc, F32 dt); +static void zEntPlayer_Move(xEnt*, xScene*, F32, xEntFrame* frame); +static void zEntPlayer_Render(xEnt*); + +// Equivalent: sda relocation and some float thing before info.rate.set +static U32 BoulderRollDoneCB() +{ + xEntShow(&globals.player.ent); + zEntPlayer_SNDPlay(ePlayerSnd_BoulderEnd, 0.0f); + + xParEmitterCustomSettings info; + if (gPTankDisable) + { + info.custom_flags = 0x35e; + xVec3Copy(&info.pos, (xVec3*)&boulderVehicle->model->Mat->pos); + xVec3Copy(&info.vel, (xVec3*)&boulderVehicle->vel); + + if (xVec3Normalize(&info.vel, &info.vel) < 0.00001f) + { + info.vel.x = 0.0f; + info.vel.y = 3.0f; + info.vel.z = 0.0f; + } + else + { + xVec3SMulBy(&info.vel, 3.0f); + } + + info.vel_angle_variation = DEG2RAD(270); + info.rate.set(3000.0f, 3000.0f, 1.0f, 0.0f); + info.life.set(0.75f, 0.75f, 1.0f, 0.0f); + info.size_birth.set(0.25f, 0.25f, 1.0f, 0.0f); + info.size_death.set(0.5f, 0.5f, 1.0f, 0.0f); + + xParEmitterEmitCustom(sEmitSpinBubbles, update_dt, &info); + xVec3AddScaled(&info.pos, &boulderVehicle->vel, 10.0f * update_dt); + xParEmitterEmitCustom(sEmitSpinBubbles, update_dt, &info); + } + else + { + zFX_SpawnBubbleHit((xVec3*)&boulderVehicle->model->Mat->pos, 50); + } + + globals.player.ent.update = zEntPlayer_Update; + globals.player.ent.move = zEntPlayer_Move; + globals.player.ent.render = zEntPlayer_Render; + + xEntBoulder_Kill(boulderVehicle); + boulderRollShouldStart = 0; + + zEntEvent(&globals.player.ent, eEventSpongeballOff); + idle_tmr = 0.0f; + + return 0; +} + +static U32 SlideTrackCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return globals.player.SlideTrackSliding & 1; +} + +static U32 SlideTrackCB(xAnimTransition*, xAnimSingle*, void*) +{ + sLasso->flags = 0; + globals.player.SlideTrackLean = 0.0f; + + if (globals.player.Health != 0 && sPlayerSndID[gCurrentPlayer][ePlayerSnd_SlideLoop] == 0) + { + zEntPlayer_SNDPlay(ePlayerSnd_SlideLoop, 0.0f); + } + + if (gCurrentPlayer == eCurrentPlayerSandy) + { + globals.player.Jump_CanDouble = 1; + } + + zEntPlayerKillCarry(); + zEntPlayer_SNDStop(ePlayerSnd_SlipLoop); + + return 0; +} + +static U32 NoslideTrackCB(xAnimTransition*, xAnimSingle*, void*) +{ + idle_tmr = 0.0f; + return 0; +} + +static U32 NoslideTrackCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return (globals.player.SlideTrackSliding & 1) == 0 && globals.player.JumpState == 0; +} + +static U32 TrackFallCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return (globals.player.SlideTrackSliding & 1) == 0 && globals.player.JumpState != 0; +} + +static U32 TrackFallCB(xAnimTransition*, xAnimSingle*, void*) +{ + globals.player.JumpState = 2; + globals.player.CanJump = 1; + return 0; +} + +static U32 TrackPrefallJumpCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return globals.player.CanJump && !globals.player.ControlOff && + globals.pad0->pressed & XPAD_BUTTON_X && tslide_inair_tmr != 0.0f && + tslide_inair_tmr < 0.25f; +} + +static U32 LedgeGrabCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return globals.player.s->ledge.tmr == -1.0f; +} + +static U32 LedgeGrabCB(xAnimTransition*, xAnimSingle*, void* object) +{ + zEntPlayer_SNDStop(ePlayerSnd_Heli); + globals.player.s->ledge.tmr = 0.00001f; + // FIXME: figure out the type of object (local variable missing from dwarf) + globals.player.s->ledge.startrot = *(*((F32**)object + 0x48 / 4) + 0xb8 / 4); + + F32 endrot = globals.player.s->ledge.endrot; + F32 startrot = globals.player.s->ledge.startrot; + if (startrot > endrot + PI) + { + globals.player.s->ledge.startrot -= 2 * PI; + } + else if (startrot < endrot - PI) + { + globals.player.s->ledge.startrot += 2 * PI; + } + + sLasso->flags = 0; + xCameraDoCollisions(0, 2); + return 0; +} + +// Equivalent: sda relocation scheduling +static U32 LedgeFinishCB(xAnimTransition*, xAnimSingle*, void* object) +{ + idle_tmr = 0.0f; + globals.player.JumpState = 1; + globals.player.JumpTimer = 0.0f; + xCameraDoCollisions(1, 2); + return 0; +} + +static U32 PatrickGrabCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return sGrabFound != 0; +} + +static U32 PatrickGrabFailed(xAnimTransition*, xAnimSingle*, void*) +{ + return sGrabFailed != 0; +} + +static U32 PatrickGrabKill(xAnimTransition*, xAnimSingle*, void*) +{ + return globals.player.carry.grabbed == NULL; +} + +static U32 PatrickGrabThrow(xAnimTransition*, xAnimSingle*, void*) +{ + if (globals.player.cheat_mode) + { + return 0; + } + + return !globals.player.ControlOff && globals.pad0->pressed & XPAD_BUTTON_O; +} + +static U32 PatrickAttackCheck(xAnimTransition*, xAnimSingle*, void*) +{ + if (globals.player.cheat_mode || zEntTeleportBox_playerIn()) + { + return 0; + } + + return !globals.player.ControlOff && globals.pad0->pressed & XPAD_BUTTON_TRIANGLE; +} + +static U32 PatrickStunCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return !globals.player.ControlOff && globals.pad0->pressed & XPAD_BUTTON_O; +} + +// Equivalent: scheduling +static U32 PatrickMeleeCB(xAnimTransition*, xAnimSingle*, void*) +{ + globals.player.DoMeleeCheck = 1; + zEntPlayer_SNDPlay(ePlayerSnd_BellyMelee, 0.0f); + return 0; +} + +static U32 PatrickGrabCB(xAnimTransition* tran, xAnimSingle*, void*) +{ + zEntPlayer_SNDPlay(ePlayerSnd_Lift1, 0.0f); + if ((xrand() & 3) == 3) + { + zEntPlayer_SNDPlayStream(ePlayerStreamSnd_Lift1); + } + + globals.player.carry.grabbed = sGrabFound; + globals.player.carry.grabTarget = 1; + globals.player.carry.grabYclear = 0; + + if (sGrabFound->baseType == eBaseTypeBoulder) + { + globals.player.carry.targetRot = + xatan2(sGrabFound->bound.sph.center.x - globals.player.ent.frame->mat.pos.x, + sGrabFound->bound.sph.center.z - globals.player.ent.frame->mat.pos.z); + } + else + { + globals.player.carry.targetRot = + xatan2(sGrabFound->model->Mat->pos.x - globals.player.ent.frame->mat.pos.x, + sGrabFound->model->Mat->pos.z - globals.player.ent.frame->mat.pos.z); + } + + globals.player.carry.grabLerpLast = 0.0f; + + xAnimState* stat = + xAnimTableGetState(globals.player.ent.model->Anim->Table, "Carry_PickupItem"); + if (stat) + { + xVec3 tmptran; + xQuat tmpquat; + iAnimEval(stat->Data->RawData[0], 1.0 / 30.0f, 1, &tmptran, &tmpquat); + + xMat4x3 objMat; + xQuatToMat(&tmpquat, &objMat); + xMat4x3 targetMat; + objMat.pos = tmptran; + xMat3x3Rot(&targetMat, &g_Y3, globals.player.carry.targetRot); + targetMat.pos = globals.player.ent.frame->mat.pos; + + xMat4x3Mul(&objMat, &objMat, &targetMat); + + if (globals.player.carry.grabbed->baseType == '/') + { + globals.player.carry.grabOffset.x = objMat.pos.x - sGrabFound->bound.sph.center.x; + globals.player.carry.grabOffset.y = + sGrabFound->bound.sph.r + (objMat.pos.y - sGrabFound->bound.sph.center.y); + globals.player.carry.grabOffset.z = objMat.pos.z - sGrabFound->bound.sph.center.z; + } + else + { + globals.player.carry.grabOffset.x = objMat.pos.x - sGrabFound->model->Mat->pos.x; + globals.player.carry.grabOffset.y = objMat.pos.y - sGrabFound->model->Mat->pos.y; + globals.player.carry.grabOffset.z = objMat.pos.z - sGrabFound->model->Mat->pos.z; + } + } + else + { + globals.player.carry.grabOffset.x = 0.0f; + globals.player.carry.grabOffset.y = 0.0f; + globals.player.carry.grabOffset.z = 0.0f; + } + + xMat3x3Rot(&globals.player.carry.spin, &g_Y3, -globals.player.carry.targetRot); + xMat3x3Mul(&globals.player.carry.spin, (xMat3x3*)sGrabFound->model->Mat, + &globals.player.carry.spin); + xVec3Init(&globals.player.carry.spin.pos, 0.0f, 0.0f, 0.0f); + + sGrabFound->chkby &= ~XENT_COLLTYPE_PLYR; + + zThrown_AddFruit(sGrabFound); + + if (sGrabFound->baseType == eBaseTypeNPC) + { + ((zNPCCommon*)sGrabFound)->SetCarryState(zNPCCARRY_PICKUP); + } + + return 0; +} + +namespace +{ + static struct foo + { + S32 anim; + U32 sndid; + void* data; + F32 time; + } player_talk; + + static U32 TalkCheck(xAnimTransition* anim, xAnimSingle*, void*) + { + return anim->UserFlags == player_talk.anim; + } + + static U32 TalkDoneCheck(xAnimTransition* anim, xAnimSingle*, void*) + { + return anim->UserFlags != player_talk.anim; + } + + static void speak_update(F32 dt) + { + if (player_talk.anim == -1) + { + return; + } + + if (player_talk.time < 0.2f || xSndIsPlaying(player_talk.sndid) != 0) + { + player_talk.time += dt; + float jawval = xJaw_EvalData(player_talk.data, player_talk.time); + globals.player.ent.model->Anim->Single->BilinearLerp[0] = jawval; + } + else + { + zEntPlayerSpeakStop(); + } + } +} // namespace + +// WIP, not equivalent +void zEntPlayerSpeakStart(U32 sndid, U32, S32 anim) +{ + zEntPlayerSpeakStop(); + + player_talk.data = xJaw_FindData(sndid); + if (player_talk.data) + { + player_talk.sndid = sndid; + player_talk.time = 0.0f; + if (anim < 0 || anim >= globals.player.s->talk_anims) + { + // wtf is happening here + U8 filter_size = globals.player.s->talk_filter_size; + U32 which = (xrand() >> 13); // / filter_size; + player_talk.anim = globals.player.s->talk_filter[which % filter_size]; + } + else + { + player_talk.anim = anim; + } + } +} + +// Equiavlent: sda scheduling reorder +void zEntPlayerSpeakStop() +{ + player_talk.anim = -1; + globals.player.ent.model->Anim->Single->BilinearLerp[0] = 0.0f; +} + +// Close, some float mismatches + regswaps +static xEnt* GetPatrickTarget(xEnt* ent) +{ + xEnt* result = NULL; + zPlatform* plat = + ent->collis->colls[0].flags & 1 ? (zPlatform*)ent->collis->colls[0].optr : NULL; + + if (plat && plat->baseType == eBaseTypePlatform && plat->plat_flags & 2) + { + xCollis* coll; + xVec3 relpos; + xMat4x3Tolocal(&relpos, (xMat4x3*)plat->model->Mat, (xVec3*)&ent->model->Mat->pos); + + relpos.z -= 2.0f; + if (SQR(relpos.x) + SQR(relpos.z)) + { + xVec3 worldpos; + worldpos.x = 0.0f; + worldpos.y = 1.23f; + worldpos.z = -2.0f; + xMat4x3Toworld(&worldpos, (xMat4x3*)plat->model->Mat, &worldpos); + + if (ent->model->Mat->at.x * (worldpos.x - ent->model->Mat->pos.x) + + ent->model->Mat->at.z * (worldpos.z - ent->model->Mat->pos.z) > + 0.0f) + { + globals.player.carry.targetRot = + xatan2(worldpos.x - globals.player.ent.frame->mat.pos.x, + worldpos.z - globals.player.ent.frame->mat.pos.z); + globals.player.carry.throwTargetRotRate = + globals.player.carry.targetRot - ent->frame->rot.angle; + CLAMP_ANGLE(globals.player.carry.throwTargetRotRate); + globals.player.carry.throwTargetRotRate /= 0.2f; + return plat; + } + } + } + + F32 bestTargetDot = -1.0f; + xVec3* bestTargetPos; + zScene* zsc = globals.sceneCur; + S32 grabbedIsFruit = zThrown_IsFruit(globals.player.carry.grabbed, NULL); + for (U32 i = 0; i < zsc->num_ents; i++) + { + xEnt* tgtent = zsc->ents[i]; + if (tgtent == globals.player.carry.grabbed || (tgtent->flags & 1) == 0) + { + continue; + } + F32 maxHeight = globals.player.carry.throwMaxHeight; + + if (tgtent->baseType == eBaseTypeStatic) + { + if (!grabbedIsFruit || !(tgtent->moreFlags & 0x8)) + { + continue; + } + if (zThrown_IsFruit(tgtent, NULL) == 0) + { + continue; + } + maxHeight = globals.player.carry.throwMaxStack; + } + else if (tgtent->baseType == eBaseTypeDestructObj) + { + if (((zEntDestructObj*)globals.player.carry.grabbed)->throw_target == 0) + { + continue; + } + } + else if (tgtent->baseType == eBaseTypeNPC) + { + // FIXME: This comparison looks like a fakematch + U32 t = ((xNPCBasic*)globals.player.carry.grabbed)->SelfType(); + if (t - NPC_TYPE_JELLYPINK <= 2 || t == NPC_TYPE_MIMEFISH) + { + continue; + } + } + else if (tgtent->baseType == eBaseTypeButton) + { + if (zThrown_IsFruit(globals.player.carry.grabbed, NULL)) + { + if ((((_zEntButton*)tgtent)->basset->buttonActFlags & (0x10000 | 0x80)) == 0) + { + continue; + } + } + else if (globals.player.carry.grabbed->baseType == eBaseTypeNPC && + ((xNPCBasic*)globals.player.carry.grabbed)->SelfType() == NPC_TYPE_TIKI_STONE) + { + if ((((_zEntButton*)tgtent)->basset->buttonActFlags & (0x2000 | 0x40)) == 0) + { + continue; + } + } + else + { + if ((((_zEntButton*)tgtent)->basset->buttonActFlags & 0x40) == 0) + { + continue; + } + } + } + else + { + continue; + } + + F32 dx = tgtent->model->Mat->pos.x - ent->model->Mat->pos.x; + F32 dy = tgtent->model->Mat->pos.y - ent->model->Mat->pos.y; + F32 dz = tgtent->model->Mat->pos.z - ent->model->Mat->pos.z; + if (SQR(dx) + SQR(dz) >= SQR(globals.player.carry.throwMaxDist) || + dy <= globals.player.carry.throwMinHeight || dy >= maxHeight || + SQR(dx) + SQR(dz) <= SQR(globals.player.carry.throwMinDist)) + { + continue; + } + + // cos of angle between (dx, 0, dz) and at (at should already be normalized) + F32 ddot = + (dx * ent->model->Mat->at.x + dz * ent->model->Mat->at.z) / xsqrt(SQR(dx) + SQR(dz)); + + if (ddot < globals.player.carry.throwMaxCosAngle) + { + continue; + } + + if (bestTargetDot != -1.0f) + { + if (tgtent->model->Mat->pos.y > bestTargetPos->y) + { + if (ddot + 0.05f < bestTargetDot) + { + continue; + } + } + else + { + if (ddot - 0.05f < bestTargetDot) + { + continue; + } + } + } + result = tgtent; + + globals.player.carry.targetRot = + xatan2(tgtent->model->Mat->pos.x - globals.player.ent.frame->mat.pos.x, + tgtent->model->Mat->pos.z - globals.player.ent.frame->mat.pos.z); + + globals.player.carry.throwTargetRotRate = + globals.player.carry.targetRot - ent->frame->rot.angle; + + CLAMP_ANGLE(globals.player.carry.throwTargetRotRate); + + globals.player.carry.throwTargetRotRate /= 0.2f; + bestTargetPos = (xVec3*)&tgtent->model->Mat->pos; + bestTargetDot = ddot; + } + return result; +} + +static U32 PatrickGrabThrowCB(xAnimTransition*, xAnimSingle*, void* object) +{ + zEntPlayer_SNDPlay(ePlayerSnd_Throw, 0.0f); + zEnt* ent = (zEnt*)object; + if (gReticleTarget && sTypeOfTarget == 3) + { + globals.player.carry.throwTarget = gReticleTarget; + } + else + { + globals.player.carry.throwTarget = GetPatrickTarget(ent); + } + + globals.player.carry.flyingToTarget = NULL; + if (globals.player.carry.grabbed && globals.player.carry.grabbed->baseType == eBaseTypeNPC) + { + ((zNPCCommon*)globals.player.carry.grabbed)->SetCarryState(zNPCCARRY_THROW); + } + + return 0; +} + +static class zNPCLassoInfo* sCurrentNPCInfo; +void zEntPlayer_LassoNotify(en_LASSO_EVENT event) +{ + switch (event) + { + case LASS_EVNT_GRABEND: + zLasso_SetGuide(sCurrentNPCInfo->lassoee, sCurrentNPCInfo->holdGuideAnim); + break; + case LASS_EVNT_ABORT: + globals.player.lassoInfo.lasso.flags = 0; + globals.player.lassoInfo.target = NULL; + break; + } +} + +static unsigned int sShouldMelee; +static U32 MeleeCheck(xAnimTransition*, xAnimSingle* anim, void*) +{ + if (!sShouldMelee) + { + return 0; + } + + if (strcmp(anim->State->Name, "DJumpApex01") == 0 && anim->Time < 0.3f) + { + return 0; + } + + return 1; +} + static U32 LassoStartCheck(xAnimTransition*, xAnimSingle*, void*) { xNPCBasic* npc = (xNPCBasic*)sLassoInfo->target; @@ -2423,6 +3117,376 @@ static U32 LassoReyankCheck(xAnimTransition*, xAnimSingle*, void*) return 0; } +static U32 LassoFailIdleSlipCheck(xAnimTransition* tran, xAnimSingle* anim, void* data) +{ + return !sLassoInfo->target && IdleSlipCheck(tran, anim, data); +} + +static U32 LassoFailIdleCheck(xAnimTransition* tran, xAnimSingle* anim, void* data) +{ + return !sLassoInfo->target && IdleCheck(tran, anim, data); +} + +static U32 LassoFailWalkCheck(xAnimTransition* tran, xAnimSingle* anim, void* data) +{ + return !sLassoInfo->target && WalkCheck(tran, anim, data); +} + +static U32 LassoFailRunCheck(xAnimTransition* tran, xAnimSingle* anim, void* data) +{ + return !sLassoInfo->target && RunAnyCheck(tran, anim, data); +} + +static U32 LassoFailRunOutOfWorldCheck(xAnimTransition* tran, xAnimSingle* anim, void* data) +{ + return !sLassoInfo->target && RunOutOfWorldCheck(tran, anim, data); +} + +static U32 LassoFailRunSlipCheck(xAnimTransition* tran, xAnimSingle* anim, void* data) +{ + return !sLassoInfo->target && RunSlipCheck(tran, anim, data); +} + +// Equivalent: sda relocation scheduling +static U32 JumpMeleeCB(xAnimTransition*, xAnimSingle*, void*) +{ + zEntPlayer_SNDPlay(ePlayerSnd_Kick, 0.0f); + if ((xrand() & 3) == 3) + { + zEntPlayer_SNDPlayStreamRandom(ePlayerStreamSnd_KickComment1, ePlayerStreamSnd_KickComment3, + 0.0f); + } + + globals.player.ent.frame->vel.y *= 0.8f; + sShouldMelee = 0; + sPlayerAttackInAir++; + return 0; +} + +// Equivalent: sda relocation scheduling +static U32 MeleeCB(xAnimTransition*, xAnimSingle*, void*) +{ + zEntPlayer_SNDPlay(ePlayerSnd_Chop, 0.0f); + if ((xrand() & 3) == 3) + { + zEntPlayer_SNDPlayStreamRandom(ePlayerStreamSnd_ChopComment1, ePlayerStreamSnd_ChopComment3, + 0.0f); + } + + sLassoInfo->target = NULL; + sShouldMelee = 0; + sPlayerAttackInAir++; + return 0; +} + +static U32 LassoStartCB(xAnimTransition*, xAnimSingle*, void* object) +{ + zEntPlayer_SNDPlay(ePlayerSnd_Heli, 0.0f); + sLassoInfo->swingTarget = NULL; + + xEnt* ent = (xEnt*)object; + zNPCCommon* npc = (zNPCCommon*)sLassoInfo->target; + if (sLassoInfo->target->baseType == eBaseTypeNPC && (npc->SelfType() & 0xffffff00) != 'NTT\0') + { + sLassoInfo->targetGuide = 1; + sCurrentNPCInfo = npc->GimmeLassInfo(); + npc->LassoNotify(LASS_EVNT_BEGIN); + zLasso_SetGuide(npc, sCurrentNPCInfo->grabGuideAnim); + } + else + { + sLassoInfo->targetGuide = NULL; + } + + zLasso_InitTimer(sLasso, 0.125f); + sLasso->flags = 0x12c3; + sLasso->tgRadius = 1.25f; + + xVec3AddScaled(&sLasso->crCenter, (xVec3*)&ent->model->Mat->up, 0.5f); + sLassoInfo->lassoRot = + xatan2(sLassoInfo->target->model->Mat->pos.x - globals.player.ent.frame->mat.pos.x, + sLassoInfo->target->model->Mat->pos.z - globals.player.ent.frame->mat.pos.z); + + return 0; +} + +// Equivalent +static U32 LassoThrowCB(xAnimTransition*, xAnimSingle*, void* object) +{ + xEnt* ent = (xEnt*)object; + + zEntPlayer_SNDStop(ePlayerSnd_Heli); + zLasso_ResetTimer(sLasso, 0.4f); + + sLasso->flags = 0x11; + sLasso->tgRadius = 0.75f * sLasso->crRadius; + + xVec3SMul(&sLasso->tgNormal, (xVec3*)&ent->model->Mat->at, -sLassoInfo->dist); + // Result is being subtracted from original instead of negated and added + sLasso->tgNormal.y += -(4.0f * sLassoInfo->dist - 5.0f); + xVec3Normalize(&sLasso->tgNormal, &sLasso->tgNormal); + xVec3Copy(&sLasso->tgCenter, &sLasso->stCenter); + xVec3AddScaled(&sLasso->tgCenter, (xVec3*)&ent->model->Mat->at, 0.5f * -sLassoInfo->dist); + + sLasso->tgCenter.y += 0.7f * sLassoInfo->dist + 0.3f; + + return 0; +} + +// Equivalent +static U32 LassoFlyCB(xAnimTransition*, xAnimSingle*, void* object) +{ + xEnt* ent = (xEnt*)object; + + zEntPlayer_SNDPlay(ePlayerSnd_LassoThrow, 0.0f); + zLasso_ResetTimer(sLasso, 0.4f * sLassoInfo->dist); + + if (sLassoInfo->targetGuide == 0) + { + sLasso->flags = 1; + xVec3Copy(&sLasso->tgCenter, xBoundCenter(&sLassoInfo->target->bound)); + xVec3AddScaled(&sLasso->tgCenter, (xVec3*)&ent->model->Mat->at, + sLassoInfo->target->model->Data->boundingSphere.radius * sLassoInfo->dist); + xVec3AddScaled(&sLasso->tgCenter, (xVec3*)&ent->model->Mat->up, + sLassoInfo->target->model->Data->boundingSphere.radius * sLassoInfo->dist); + sLasso->tgRadius = 1.5f * sLassoInfo->target->model->Data->boundingSphere.radius; + + xVec3SMul(&sLasso->tgNormal, (xVec3*)&ent->model->Mat->at, 1.0f); + // Result is being subtracted from original instead of negated and added + sLasso->tgNormal.y += -(4.0f * sLassoInfo->dist - 5.0f); + xVec3Normalize(&sLasso->tgNormal, &sLasso->tgNormal); + } + else + { + sLasso->flags = 1; + zLasso_InterpToGuide(sLasso); + } + + sLasso->tgSlack = 0.5f; + return 0; +} + +static U32 LassoDestroyCB(xAnimTransition*, xAnimSingle*, void*) +{ + zEntPlayer_SNDPlay(ePlayerSnd_LassoYank, 0.17f); + zEntPlayer_SNDPlayStreamRandom(ePlayerStreamSnd_RopingComment1, ePlayerStreamSnd_RopingComment3, + 0.133f); + + if (sLassoInfo->targetGuide == 0) + { + zLasso_ResetTimer(sLasso, 0.5f); + sLassoInfo->destroy = 1; + sLasso->flags = 0x521; + + xVec3Copy(&sLasso->tgCenter, xBoundCenter(&sLassoInfo->target->bound)); + sLasso->tgRadius = 0.75f * sLassoInfo->target->model->Data->boundingSphere.radius; + xVec3Init(&sLasso->tgNormal, 0.0f, 1.0f, 0.0f); + return 0; + } + else + { + sLassoInfo->zeroAnim = sLassoInfo->target->model->Anim->Single->State; + ((zNPCCommon*)sLassoInfo->target)->LassoNotify(LASS_EVNT_GRABSTART); + sLasso->flags = 0x4c01; + return 0; + } +} + +static U32 LassoYankCB(xAnimTransition*, xAnimSingle*, void*) +{ + zEntPlayer_SNDPlay(ePlayerSnd_LassoYank, 0.17f); + zEntPlayer_SNDPlayStreamRandom(ePlayerStreamSnd_RopingComment1, ePlayerStreamSnd_RopingComment3, + 0.133f); + + if (sLassoInfo->targetGuide && sLassoInfo->target) + { + ((zNPCCommon*)sLassoInfo->target)->LassoNotify(LASS_EVNT_YANK); + } + + return 0; +} + +// Equivalent: sda relocation scheduling +static U32 MeleeStopCB(xAnimTransition*, xAnimSingle*, void*) +{ + idle_tmr = 0.0f; + + if (globals.player.SundaeTimer < 0.0f) + { + globals.player.SpeedMult = 1.0f; + } + else + { + globals.player.SpeedMult = globals.player.g.SundaeMult; + } + + sShouldMelee = 0; + return 0; +} + +static U32 SpatulaMeleeStopCB(xAnimTransition* tran, xAnimSingle* anim, void* data) +{ + MeleeStopCB(tran, anim, data); + SpatulaGrabCB(tran, anim, data); + return 0; +} + +// Equivalent: sda relocation scheduling +static U32 LassoStopCB(xAnimTransition*, xAnimSingle*, void*) +{ + idle_tmr = 0.0f; + sLasso->flags = 0; + + if (sLassoInfo->targetGuide) + { + if (sLassoInfo->target) + { + ((zNPCCommon*)sLassoInfo->target)->LassoNotify(LASS_EVNT_YANK); + } + } + else if (sLassoInfo->destroy && sLassoInfo->target) + { + zEntEvent(sLassoInfo->target, eEventHit); + } + + sLassoInfo->destroy = 0; + sLassoInfo->target = NULL; + zLasso_SetGuide(NULL, NULL); + zRumbleStart(SDR_LassoDestroy); + return 0; +} + +static U32 LassoSwingGroundedBeginCheck(xAnimTransition*, xAnimSingle*, void*) +{ + if (globals.sceneCur->sceneID == 'B201' && globals.player.JumpState == 0) + { + sLassoInfo->swingTarget = NULL; + gReticleTarget = NULL; + sTypeOfTarget = 0; + } + + return sLassoInfo->swingTarget && globals.player.JumpState == 0; +} + +static U32 LassoSwingBeginCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return sLassoInfo->swingTarget && globals.player.JumpState != 0; +} + +static U32 LassoSwingReleaseCheck(xAnimTransition*, xAnimSingle*, void*) +{ + return (!globals.player.ControlOff && (globals.pad0->pressed & XPAD_BUTTON_X) && + sSwingTimeElapsed > 0.5f) || + sLassoInfo->swingTarget == NULL || !(sLassoInfo->swingTarget->flags & 1); +} + +static U32 LassoSwingBeginCB(xAnimTransition*, xAnimSingle*, void* object) +{ + xEnt* ent = (xEnt*)object; + + sLassoInfo->target = NULL; + gReticleTarget = NULL; + + if (sLasso->flags & 1) + { + sLasso->flags = 1; + zLasso_ResetTimer(sLasso, 0.133f); + xVec3Copy(&sLasso->tgCenter, &sLasso->stCenter); + } + else + { + sLasso->flags = 0x1043; + zLasso_InitTimer(sLasso, 0.133f); + xVec3Copy(&sLasso->stNormal, (xVec3*)&ent->model->Mat->right); + zEntPlayer_SNDPlay(ePlayerSnd_Heli, 0.0f); + } + + sLasso->tgSlack = 0.5f; + sLasso->tgRadius = sLassoInfo->swingTarget->model->Data->boundingSphere.radius; + xVec3Copy(&sLasso->tgNormal, (xVec3*)&ent->model->Mat->right); + xVec3Copy(&globals.player.HangVel, (xVec3*)&ent->frame->vel); + sSwingTimeElapsed = 0.0f; + + zCameraSetBbounce(false); + zCameraSetLongbounce(false); + zCameraSetHighbounce(false); + return 0; +} + +static U32 LassoSwingGroundedBeginCB(xAnimTransition* tran, xAnimSingle* anim, void* object) +{ + xEnt* ent = (xEnt*)object; + JumpCB(tran, anim, object); + + ent->frame->vel.y *= 0.5f; + LassoSwingBeginCB(tran, anim, object); + return 0; +} + +static U32 LassoSwingTossCB(xAnimTransition*, xAnimSingle*, void*) +{ + zEntPlayer_SNDStop(ePlayerSnd_Heli); + zEntPlayer_SNDPlay(ePlayerSnd_LassoThrow, 0.0f); + + sLasso->flags = 1; + zLasso_ResetTimer(sLasso, 0.117f); + xVec3Copy(&sLasso->tgCenter, xBoundCenter(&sLassoInfo->swingTarget->bound)); + xVec3AddScaled(&sLasso->tgCenter, (xVec3*)&sLassoInfo->swingTarget->model->Mat->up, -0.6f); + xVec3Copy(&sLasso->tgNormal, (xVec3*)&sLassoInfo->swingTarget->model->Mat->up); + + if (xVec3Dot(&sLasso->tgNormal, &sLasso->stNormal) < 0.0f) + { + xVec3Inv(&sLasso->tgNormal, &sLasso->tgNormal); + } + + sLasso->tgRadius = 0.1f; + return 0; +} + +static U32 LassoSwingCB(xAnimTransition*, xAnimSingle* anim, void*) +{ + sLasso->flags = 0xc21; + zLasso_ResetTimer(sLasso, 0.0f); + + anim->BilinearLerp[0] = 1.0f; + anim->Blend->BilinearLerp[0] = 1.0f; + + zCameraEnableLassoCam(); + zCameraSetLassoCamFactor(1.0f); + return 0; +} + +// Equivalent: sda/float scheduling crap +static U32 LassoSwingGroundedCB(xAnimTransition*, xAnimSingle*, void*) +{ + zEntPlayer_SNDStop(ePlayerSnd_Heli); + idle_tmr = 0.0f; + sTimeToRetarget = 0.5f; + sLassoInfo->swingTarget = NULL; + sLasso->flags = 0; + sLassoCamLinger = 1; + + return 0; +} + +// Really odd scheduling. Maybe equivalent? +static U32 LassoSwingReleaseCB(xAnimTransition* tran, xAnimSingle* anim, void* object) +{ + zEntPlayer_SNDStop(ePlayerSnd_Heli); + idle_tmr = 0.0f; + sTimeToRetarget = 0.5f; + sLassoInfo->canCopter = 1; + globals.player.Jump_CanDouble = 1; + globals.player.IsDJumping = 0; + sLassoCamLinger = 1; + sLassoInfo->swingTarget = NULL; + sLasso->flags = 0; + + JumpCB(tran, anim, object); + + return 0; +} + bool zEntPlayer_IsSneaking() { if (gCurrentPlayer != eCurrentPlayerSpongeBob) @@ -2667,8 +3731,10 @@ void zEntPlayer_GiveLevelPickupCurrentLevel(S32 quantity) } } -static void _SetupRumble(_tagePlayerSnd, _tagRumbleType, float) +static void _SetupRumble(_tagePlayerSnd player_snd, _tagRumbleType type, float time) { + sPlayerRumbleType[player_snd] = type; + sPlayerRumbleTime[player_snd] = time; } // Close. missing redundant float loads, maybe equivalent. @@ -3600,7 +4666,7 @@ void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) // TODO: Move these to their headers -WEAK U8 xSndIsPlaying(U32 assetID) +WEAK U32 xSndIsPlaying(U32 assetID) { return iSndIsPlaying(assetID); } diff --git a/src/SB/Game/zEntPlayer.h b/src/SB/Game/zEntPlayer.h index 5e669ac3..b0777d78 100644 --- a/src/SB/Game/zEntPlayer.h +++ b/src/SB/Game/zEntPlayer.h @@ -388,6 +388,7 @@ void zEntPlayer_ShadowModelDisable(); void zEntPlayerJumpStart(class xEnt* ent, class zJumpParam* jump); void zEntPlayer_setBoulderMode(U32 mode); +void zEntPlayer_GiveHealth(S32); void zEntPlayer_GiveSpatula(S32); void zEntPlayer_GivePatsSocksCurrentLevel(S32 quantity); @@ -412,6 +413,8 @@ void zEntPlayer_SNDSetVol(_tagePlayerSnd player_snd, F32 new_vol); void zEntPlayer_SNDSetPitch(_tagePlayerSnd player_snd, F32 new_pitch); void zEntPlayer_SNDStop(_tagePlayerSnd player_snd); +void zEntPlayerSpeakStop(); + void zEntPlayerControlOff(zControlOwner owner); void zEntPlayerControlOn(zControlOwner owner); diff --git a/src/SB/Game/zEntTrigger.cpp b/src/SB/Game/zEntTrigger.cpp index 39294ebf..622d093b 100644 --- a/src/SB/Game/zEntTrigger.cpp +++ b/src/SB/Game/zEntTrigger.cpp @@ -2,10 +2,6 @@ #include "xEvent.h" -extern F32 _670; -extern F32 _671_0; -extern F32 _746_1; - void zEntTriggerInit(void* ent, void* asset) { zEntTriggerInit((zEntTrigger*)ent, (xEntAsset*)asset); @@ -29,15 +25,15 @@ void zEntTriggerInit(zEntTrigger* ent, xEntAsset* asset) xVec3Sub(&var_20, &var_20, &asset->pos); xVec3Sub(&var_2C, &var_2C, &asset->pos); - xVec3Lerp(&var_38, &var_2C, &var_20, _670); + xVec3Lerp(&var_38, &var_2C, &var_20, 0.5f); xMat3x3RMulVec(&var_38, &ent->triggerMatrix, &var_38); xVec3Add(&ent->triggerMatrix.pos, &var_38, &asset->pos); - ent->triggerBox.lower.x = _671_0 * (var_20.x - var_2C.x); - ent->triggerBox.lower.y = _671_0 * (var_20.y - var_2C.y); - ent->triggerBox.lower.z = _671_0 * (var_20.z - var_2C.z); + ent->triggerBox.lower.x = -0.5f * (var_20.x - var_2C.x); + ent->triggerBox.lower.y = -0.5f * (var_20.y - var_2C.y); + ent->triggerBox.lower.z = -0.5f * (var_20.z - var_2C.z); ent->triggerBox.upper.x = -ent->triggerBox.lower.x; ent->triggerBox.upper.y = -ent->triggerBox.lower.y; ent->triggerBox.upper.z = -ent->triggerBox.lower.z; @@ -101,7 +97,7 @@ void zEntTriggerUpdate(zEntTrigger* trig, xScene*, F32) xMat4x3Tolocal(&xformVec, &trig->triggerMatrix, chkPos); iBoxIsectVec(&trig->triggerBox, &xformVec, &isect); - collide = (isect.penned <= _746_1); + collide = (isect.penned <= 0.0f); break; } @@ -115,7 +111,7 @@ void zEntTriggerUpdate(zEntTrigger* trig, xScene*, F32) iSphereIsectVec(&sphere, chkPos, &isect); - collide = (isect.penned <= _746_1); + collide = (isect.penned <= 0.0f); break; } @@ -130,7 +126,7 @@ void zEntTriggerUpdate(zEntTrigger* trig, xScene*, F32) iCylinderIsectVec(&cylinder, chkPos, &isect); - collide = (isect.penned <= _746_1); + collide = (isect.penned <= 0.0f); break; } @@ -144,7 +140,7 @@ void zEntTriggerUpdate(zEntTrigger* trig, xScene*, F32) iSphereIsectVec(&sphere, chkPos, &isect); - collide = (isect.penned <= _746_1); + collide = (isect.penned <= 0.0f); break; } @@ -240,7 +236,7 @@ bool zEntTriggerHitsSphere(const zEntTrigger& trig, const xSphere& o, const xVec tasset = zEntTriggerAsset(trig); - if (tasset->flags & 0x1 && dir.dot(tasset->direction) <= _746_1) + if (tasset->flags & 0x1 && dir.dot(tasset->direction) <= 0.0f) { return false; } diff --git a/src/SB/Game/zFX.h b/src/SB/Game/zFX.h index 581fe72d..d03dea25 100644 --- a/src/SB/Game/zFX.h +++ b/src/SB/Game/zFX.h @@ -163,7 +163,7 @@ void xDebugAddTweak(const char* unk1, const char* unk2, const tweak_callback* un void xMat3x3RMulVec(xVec3* result, const xMat3x3* mat, const xVec3* vec); -xFXRing* zFXMuscleArmWave(xVec3* pos); +xFXRing* zFXMuscleArmWave(const xVec3* pos); void zFX_SpawnBubbleMenuTrail(const xVec3* pos, U32 num, const xVec3* pos_rnd, const xVec3* vel_rnd); diff --git a/src/SB/Game/zGameState.cpp b/src/SB/Game/zGameState.cpp index c4d45ca9..479f4c8b 100644 --- a/src/SB/Game/zGameState.cpp +++ b/src/SB/Game/zGameState.cpp @@ -251,7 +251,6 @@ void zGameStateSwitch(S32 theNewState) } } -#ifdef NON_MATCHING void zGameModeSwitch(eGameMode modeNew) { eGameMode modeOld = gGameMode; @@ -284,4 +283,3 @@ void zGameModeSwitch(eGameMode modeNew) zEntEventAllOfType(sGameMode_DispatchTable[modeNew], eBaseTypeDispatcher); } -#endif diff --git a/src/SB/Game/zGlobals.h b/src/SB/Game/zGlobals.h index 8179a107..348052ad 100644 --- a/src/SB/Game/zGlobals.h +++ b/src/SB/Game/zGlobals.h @@ -210,7 +210,7 @@ struct zPlayerGlobals F32 IdleSitTimer; S32 Transparent; zEnt* FireTarget; - U32 ControlOff; + U32 ControlOff; // 0x1788 U32 ControlOnEvent; // Offset: 0x1790 @@ -219,13 +219,13 @@ struct zPlayerGlobals xVec3 AutoMoveTarget; xBase* AutoMoveObject; zEnt* Diggable; - F32 DigTimer; + F32 DigTimer; // 0x17AC zPlayerCarryInfo carry; zPlayerLassoInfo lassoInfo; xModelTag BubbleWandTag[2]; - xModelInstance* model_wand; + xModelInstance* model_wand; // 0x19E0 xEntBoulder* bubblebowl; - F32 bbowlInitVel; + F32 bbowlInitVel; // 0x19E8 zEntHangable* HangFound; zEntHangable* HangEnt; zEntHangable* HangEntLast; @@ -317,7 +317,7 @@ struct zGlobals : xGlobals zPlayerGlobals player; zAssetPickupTable* pickupTable; // 0x1FB8 zCutsceneMgr* cmgr; // 0x1FBC - zScene* sceneCur; + zScene* sceneCur; // 0x1FC0 zScene* scenePreload; }; diff --git a/src/SB/Game/zGust.cpp b/src/SB/Game/zGust.cpp index 62b7acee..4086a12b 100644 --- a/src/SB/Game/zGust.cpp +++ b/src/SB/Game/zGust.cpp @@ -1,19 +1,343 @@ +#include "xstransvc.h" +#include "xMath.h" +#include "xMath3.h" +#include "xEvent.h" +#include "xString.h" +#include "xVec3.h" +#include "xVec3Inlines.h" + #include "zGust.h" +#include "zParEmitter.h" +#include "zScene.h" #include -#if 0 -// WIP. +static zGust* gusts; +static U16 ngusts; +static zParEmitter* sGustDustEmitter; +static zParEmitter* sGustDebrisEmitter; + +S32 zGustEventCB(xBase* from, xBase* to, U32 toEvent, const float* toParam, xBase* b); + +static void zGustInit(zGust* g, zGustAsset* a) +{ + xBaseInit(g, a); + g->eventFunc = zGustEventCB; + g->asset = a; + g->flags = a->flags; + + if (g->linkCount) + { + g->link = (xLinkAsset*)&g->asset[1]; + } + else + { + g->link = NULL; + } + + g->debris_timer = 0.15f; +} + +static void zGustSetup(zGust* g) +{ + g->volume = (zVolume*)zSceneFindObject(g->asset->volumeID); + g->fx_volume = (zVolume*)zSceneFindObject(g->asset->effectID); +} + +// NOTE(jelly): equivalent, reloading global variable meme +void zGustInit() +{ + ngusts = xSTAssetCountByType('GUST'); + + if (ngusts) + { + gusts = (zGust*)xMemAllocSize(sizeof(zGust) * ngusts); + for (U16 i = 0; i < ngusts; i++) + { + U32 size; + zGustAsset* asset = (zGustAsset*)xSTFindAssetByType('GUST', i, &size); + zGustInit(&gusts[i], asset); + } + } + else + { + gusts = NULL; + } +} + +void zGustSetup() +{ + if (gusts) + { + for (U16 i = 0; i < ngusts; i++) + { + zGustSetup(&gusts[i]); + } + sGustDustEmitter = zParEmitterFind(xStrHash("PAREMIT_GUST_DUST")); + sGustDebrisEmitter = zParEmitterFind(xStrHash("PAREMIT_GUST_DEBRIS")); + } +} + +void zGustTurnOn(zGust* g) + +{ + g->flags |= 1; + g->debris_timer = 0.15f; +} + +void zGustTurnOff(zGust* g) +{ + g->flags &= ~1; +} + +void zGustToggleOn(zGust* g) +{ + g->flags ^= 1; + g->debris_timer = 0.15f; +} + +zGust* zGustGetGust(U16 n) +{ + if (gusts) + { + return &gusts[n]; + } + + return NULL; +} + +// NOTE(jelly): non-matching +void zGustUpdateEnt(xEnt* ent, xScene* sc, float dt, void* gdata) +{ + zGustData* data = (zGustData*)gdata; + + if (!gusts) + return; + + xCollis coll; + coll.flags = 0; + for (U32 i = 0; i < ngusts; i++) + { + if (gusts[i].flags & 1) + { + xBoundHitsBound(&ent->bound, &gusts[i].volume->asset->bound, &coll); + if (coll.flags & 1) + { + U32 j; + U32 minidx; + for (j = 0; j < 4; j++) + { + if (data->lerp[j] < 2.0f) + { + minidx = j; + if (data->g[j] == &gusts[i]) + { + break; + } + } + } + + if (j == 4) + { + data->g[minidx] = &gusts[i]; + data->lerp[minidx] = 1.0E-7; + } + } + else + { + for (U32 j = 0; j < 4; j++) + { + if (data->g[0] == &gusts[i] && data->lerp[0] == 1.0f) + { + data->lerp[j] = -1.0f; + break; + } + } + } + } + } + + for (U32 i = 0; i < 4; i++) + { + zGust* g = data->g[i]; + if (g) + { + if (g->flags & 1) + { + float lerpinc = g->asset->fade; + if (dt >= lerpinc) + { + if (!(data->lerp[i] < 1.0f)) + { + data->lerp[i] = 1.0f; + continue; + } + } + else + { + lerpinc = dt / lerpinc; + if (data->lerp[i] >= 0.0f) + { + data->lerp[i] += lerpinc; + if (data->lerp[i] >= 1.0f) + { + data->lerp[i] = 1.0f; + } + } + else + { + data->lerp[i] += lerpinc; + if (!(data->lerp[i] >= 0.0f)) + { + continue; + } + } + } + } + + data->g[i] = NULL; + data->lerp[i] = 0.0f; + } + } + + data->gust_on = 0; + + for (U32 i = 0; i < 4; i++) + { + if (data->g[i]) + { + data->gust_on = 1; + + xVec3 dpos; + xVec3SMul(&dpos, &data->g[i]->asset->vel, dt * xabs(data->lerp[i])); + xVec3AddTo(&ent->frame->mat.pos, &dpos); + } + } +} + +void zGustSave(zGust* g, xSerial* s) +{ + xBaseSave(g, s); +} + +void zGustLoad(zGust* g, xSerial* s) +{ + xBaseLoad(g, s); +} + +void zGustReset(zGust* g) +{ + xBaseReset(g, g->asset); + g->flags = g->asset->flags; +} + +S32 zGustEventCB(xBase* from, xBase* to, U32 toEvent, const float* toParam, xBase* b) +{ + switch (toEvent) + { + case eEventOn: + zGustTurnOn((zGust*)to); + break; + + case eEventOff: + zGustTurnOff((zGust*)to); + break; + + case eEventToggle: + zGustToggleOn((zGust*)to); + break; + + case eEventReset: + zGustReset((zGust*)to); + break; + } + + return 1; +} + +// NOTE(jelly): equivalent? i think it's just registers & float scheduling +static void UpdateGustFX(zGust* g, float seconds) +{ + S32 i; + + if (g->asset->partMod <= 0.0f) + return; + + g->debris_timer -= seconds; + + if (!(g->debris_timer <= 0.0f)) + return; + + zVolume* volume = !g->asset->effectID ? g->volume : g->fx_volume; + xVolumeAsset* asset = volume->asset; + + S32 vol_area = ((asset->bound.sph.r - asset->bound.box.box.lower.x) * + (asset->bound.box.box.upper.z - asset->bound.box.box.lower.z)); + + if (vol_area > 1000) + { + g->debris_timer = 1000000.0f; + return; + } + + S32 total_debris = vol_area >> 5; + if (total_debris > 5) + total_debris = 5; + else if (total_debris < 1) + total_debris = 1; + + g->debris_timer = xurand() * 0.15f + 0.15f; + + xParEmitter* e = g->asset->flags & 2 ? sGustDustEmitter : sGustDebrisEmitter; + + if (!e) + return; + + xParEmitterCustomSettings info; + info.custom_flags = 0x302; // TODO(jelly): i'm guessing this is constants or'd together + + for (i = 0; i < total_debris; i++) + { + if (g->asset->effectID == 0) + { + asset = g->volume->asset; + xBBox* box = &asset->bound.box; + + info.pos = box->box.lower; + info.pos.x = (asset->bound.sph.r - box->box.lower.x) * xurand() + info.pos.x; + info.pos.z = (box->box.upper.z - box->box.lower.z) * xurand() + info.pos.z; + info.vel.x = 0.0f; + info.vel.y = 5.0f; + info.vel.z = 0.0f; + info.life.val[0] = (box->box.upper.y - box->box.lower.y) / 5.0f * 2.0f; + } + else + { + asset = g->fx_volume->asset; + xBBox* box = &asset->bound.box; + + info.pos.x = (asset->bound.sph.r - box->box.lower.x) * xurand() + box->box.lower.x; + info.pos.y = (box->box.upper.y - box->box.lower.y) * xurand() + box->box.lower.y; + info.pos.z = (box->box.upper.z - box->box.lower.z) * xurand() + box->box.lower.z; + info.vel.x = 1.5f * g->asset->vel.x; + info.vel.y = 1.5f * g->asset->vel.y; + info.vel.z = 1.5f * g->asset->vel.z; + info.life.val[0] = 7.5f * g->asset->fade; + } + + info.life.val[0] *= g->asset->partMod; + xParEmitterEmitCustom(e, 1.0f / 30.0f, &info); + } +} + void zGustUpdateFX(F32 seconds) { for (S32 i = 0; i < ngusts; i++) { - zGust* curr = gusts[i]; + zGust* curr = &gusts[i]; if (curr->flags & 1) { UpdateGustFX(curr, seconds); } } } - -#endif diff --git a/src/SB/Game/zGust.h b/src/SB/Game/zGust.h index b520fc63..a30bf70e 100644 --- a/src/SB/Game/zGust.h +++ b/src/SB/Game/zGust.h @@ -27,6 +27,13 @@ struct zGust : xBase F32 debris_timer; }; +struct zGustData +{ + U32 gust_on; + zGust* g[4]; + float lerp[4]; +}; + void zGustInit(); void zGustSetup(); zGust* zGustGetGust(U16 n); diff --git a/src/SB/Game/zLasso.h b/src/SB/Game/zLasso.h index eb36a76b..78647a84 100644 --- a/src/SB/Game/zLasso.h +++ b/src/SB/Game/zLasso.h @@ -34,6 +34,9 @@ struct zLasso }; void zLasso_scenePrepare(); -void zLasso_InitTimer(zLasso* lasso, float interpTime); +void zLasso_InitTimer(zLasso* lasso, F32 interpTime); +void zLasso_ResetTimer(zLasso* lasso, F32 interpTime); +void zLasso_SetGuide(xEnt* ent, xAnimState* lassoAnim); +void zLasso_InterpToGuide(zLasso* lasso); #endif diff --git a/src/SB/Game/zLightning.h b/src/SB/Game/zLightning.h index a202e9a2..1ac428fa 100644 --- a/src/SB/Game/zLightning.h +++ b/src/SB/Game/zLightning.h @@ -101,14 +101,14 @@ void zLightningKill(zLightning* l); void RenderLightning(zLightning* l); void zLightningRender(); void zLightningModifyEndpoints(zLightning* l, xVec3* start, xVec3* end); -void xDebugAddTweak(char* name, U8* property, U8 param_3, U8 param_4, - tweak_callback* callback, void* param_6, U32 param_7); +void xDebugAddTweak(char* name, U8* property, U8 param_3, U8 param_4, tweak_callback* callback, + void* param_6, U32 param_7); void xDebugAddFlagTweak(char* name, U32* property, U32 param_3, tweak_callback* callback, void* param_5, U32 param_6); -void xDebugAddSelectTweak(char* name, U32* param_2, char** param_3, U32* param_4, - U32 param_5, tweak_callback* callback, void* param_7, U32 param_8); -void xDebugAddTweak(char* name, S16* property, S16 param_3, S16 param_4, - tweak_callback* callback, void* param_6, U32 param_7); +void xDebugAddSelectTweak(char* name, U32* param_2, char** param_3, U32* param_4, U32 param_5, + tweak_callback* callback, void* param_7, U32 param_8); +void xDebugAddTweak(char* name, S16* property, S16 param_3, S16 param_4, tweak_callback* callback, + void* param_6, U32 param_7); void zLightningInit(); void zLightningUpdate(F32 seconds); diff --git a/src/SB/Game/zMovePoint.h b/src/SB/Game/zMovePoint.h index 3710dd0f..59b39f79 100644 --- a/src/SB/Game/zMovePoint.h +++ b/src/SB/Game/zMovePoint.h @@ -9,6 +9,8 @@ struct zMovePoint : xMovePoint { + F32 RadiusZone(); + F32 Delay(); U32 NumNodes(); U8 IsOn(); }; diff --git a/src/SB/Game/zNPCGoalCommon.h b/src/SB/Game/zNPCGoalCommon.h index c212c88a..1c154040 100644 --- a/src/SB/Game/zNPCGoalCommon.h +++ b/src/SB/Game/zNPCGoalCommon.h @@ -15,7 +15,10 @@ struct zNPCGoalCommon : xGoal S32 flg_info : 16; // 0x48 S32 flg_user : 16; // 0x4a - zNPCGoalCommon(S32 goalID); + zNPCGoalCommon(S32 goalID) : xGoal(goalID) + { + flg_npcgauto |= ~(1 << 3); + } U32 DoAutoAnim(en_NPC_GOAL_SPOT gspot, S32 forceRestart); U32 DoExplicitAnim(U32 anid, S32 forceRestart); diff --git a/src/SB/Game/zNPCGoalDuplotron.cpp b/src/SB/Game/zNPCGoalDuplotron.cpp index ba5089b3..e6ea0b44 100644 --- a/src/SB/Game/zNPCGoalDuplotron.cpp +++ b/src/SB/Game/zNPCGoalDuplotron.cpp @@ -10,9 +10,6 @@ #include "xEvent.h" #include "xScrFx.h" -extern F32 _816_0; // 20.0f -extern F32 _840_3; // 0.0f - xFactoryInst* GOALCreate_Duplotron(S32 who, RyzMemGrow* grow, void*) { xGoal* goal = NULL; @@ -37,7 +34,7 @@ xFactoryInst* GOALCreate_Duplotron(S32 who, RyzMemGrow* grow, void*) S32 zNPCGoalDuploLive::Enter(F32 dt, void* updCtxt) { livestat = LIVESTAT_NORMAL; - tmr_chkPlyrDist = _816_0; + tmr_chkPlyrDist = 20.0f; return zNPCGoalCommon::Enter(dt, updCtxt); } @@ -53,7 +50,7 @@ S32 zNPCGoalDuploLive::Process(en_trantype* trantype, F32 dt, void* updCtxt, xSc { case LIVESTAT_NORMAL: { - if (tmr_chkPlyrDist < _840_3) + if (tmr_chkPlyrDist < 0.0f) { CheckPlayer(); } diff --git a/src/SB/Game/zNPCGoalStd.cpp b/src/SB/Game/zNPCGoalStd.cpp index 27da8029..5de65454 100644 --- a/src/SB/Game/zNPCGoalStd.cpp +++ b/src/SB/Game/zNPCGoalStd.cpp @@ -1,48 +1,477 @@ +#include "xMath.h" #include "zNPCGoalStd.h" +#include "zNPCGoals.h" #include -#include "xNPCBasic.h" - +// Nonmatching: not finished #if 0 - -#else -zNPCGoalCommon::zNPCGoalCommon(S32 goalID) : xGoal(goalID) +xFactoryInst* GOALCreate_Standard(S32 who, RyzMemGrow* grow, void*) { - this->flg_npcgauto |= ~0x8; + xFactoryInst* std = NULL; + + switch (who) + { + case NPC_GOAL_IDLE: + std = new (who, grow) zNPCGoalIdle(who); + break; + case NPC_GOAL_WAITING: + std = new (who, grow) zNPCGoalWaiting(who); + break; + case NPC_GOAL_WANDER: + std = new (who, grow) zNPCGoalWander(who); + break; + case NPC_GOAL_PATROL: + std = new (who, grow) zNPCGoalPatrol(who); + break; + } + + return std; } #endif -#if 0 -WEAK xGoal::xGoal(S32 goalID) +void GOALDestroy_Goal(xFactoryInst* inst) { - this->goalID = goalID; - this->flg_able = 0; - this->stat = GOAL_STAT_UNKNOWN; + delete inst; +} + +S32 zNPCGoalPushAnim::Enter(F32 dt, void* updCtxt) +{ + flg_pushanim &= (1 << 16) | (1 << 2) | (1 << 1); + lastAnimTime = -1.0f; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalPushAnim::Exit(F32 dt, void* updCtxt) +{ + flg_pushanim = 0; + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalPushAnim::Resume(F32 dt, void* updCtxt) +{ + flg_pushanim |= (1 << 0); + + return zNPCGoalCommon::Resume(dt, updCtxt); +} + +S32 zNPCGoalLoopAnim::Exit(F32 dt, void* updCtxt) +{ + UnmolestAnim(); + return xGoal::Exit(dt, updCtxt); +} + +void zNPCGoalLoopAnim::MolestLoopAnim() +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + xAnimState* state = npc->AnimFindState(anid_stage[1]); + origAnimFlags = state->Flags; + animWeMolested = state->ID; + state->Flags &= ~(1 << 5); + state->Flags |= (1 << 4); +} + +void zNPCGoalLoopAnim::UnmolestAnim() +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + if (animWeMolested == 0) + { + return; + } + + xAnimState* state = npc->AnimFindState(animWeMolested); + state->Flags = origAnimFlags; + + animWeMolested = 0; + origAnimFlags = 0; +} + +void zNPCGoalLoopAnim::LoopCountSet(S32 num) +{ + cnt_loop = (num >= 1) ? num : 1; + flg_info |= (1 << 4); +} + +void zNPCGoalLoopAnim::UseDefaultAnims() +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + anid_stage[1] = npc->AnimPick(GetID(), NPC_GSPOT_RESUME, this); + + U32 id = npc->AnimPick(GetID(), NPC_GSPOT_START, this); + if (id == anid_stage[1]) + { + id = 0; + } + anid_stage[0] = id; + if (id != 0) + { + flg_loopanim |= (1 << 2); + } + + id = npc->AnimPick(GetID(), NPC_GSPOT_FINISH, this); + if (id == anid_stage[1]) + { + id = 0; + } + anid_stage[2] = id; + if (id != 0) + { + flg_loopanim |= (1 << 3); + } +} + +void zNPCGoalLoopAnim::ValidateStages() +{ + if (anid_stage[0] == anid_stage[1]) + { + anid_stage[0] = 0; + flg_loopanim &= ~(1 << 2); + } + if (anid_stage[2] == anid_stage[1]) + { + anid_stage[2] = 0; + flg_loopanim &= ~(1 << 3); + } + + if (flg_loopanim & (1 << 2) && anid_stage[0] == 0) + { + flg_loopanim &= ~(1 << 2); + } + if (flg_loopanim & (1 << 3) && anid_stage[2] == 0) + { + flg_loopanim &= ~(1 << 3); + } +} + +S32 zNPCGoalIdle::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + npc->tmr_fidget = + npc->cfg_npc->tym_fidget * (0.25f * (xurand() - 0.5f)) + npc->cfg_npc->tym_fidget; + npc->VelStop(); + + flg_user = (1 << 0); + + xEntDrive* drive = npc->drv_data; + if (drive == NULL || (drive->driver == NULL && drive->odriver == NULL)) + { + npc->flags2.flg_colCheck = 0; + npc->flags2.flg_penCheck = 0; + npc->pflags &= (U8) ~((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); + } + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalIdle::Exit(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + npc->RestoreColFlags(); + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalIdle::Suspend(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + npc->RestoreColFlags(); + + return xGoal::Suspend(dt, updCtxt); } -#endif -U8 xNPCBasic::PhysicsFlags() const +S32 zNPCGoalIdle::Resume(F32 dt, void* updCtxt) { - return 0; + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + npc->tmr_fidget = + npc->cfg_npc->tym_fidget * (0.25f * (xurand() - 0.5f)) + npc->cfg_npc->tym_fidget; + + if (npc->nav_dest == NULL) + { + npc->MvptCycle(); + } + + flg_user = (1 << 0); + + xEntDrive* drive = npc->drv_data; + if (drive == NULL || (drive->driver == NULL && drive->odriver == NULL)) + { + npc->flags2.flg_colCheck = 0; + npc->flags2.flg_penCheck = 0; + npc->pflags &= (U8) ~((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); + } + + return xGoal::Resume(dt, updCtxt); } -U8 xNPCBasic::ColPenByFlags() const +S32 zNPCGoalIdle::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) { - return 0; + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + S32 nextgoal = 0; + + if (npc->nav_dest != NULL && npc->npcset.allowPatrol) + { + *trantype = GOAL_TRAN_PUSH; + nextgoal = NPC_GOAL_PATROL; + } + else if (!(flg_idle & (1 << 0)) && npc->tmr_fidget < 0.0f) + { + *trantype = GOAL_TRAN_PUSH; + nextgoal = NPC_GOAL_FIDGET; + } + else + { + zMovePoint* nav_curr = npc->nav_curr; + if (npc->npcset.allowWander && nav_curr != NULL && nav_curr->Delay() > 0.0f && + nav_curr->RadiusZone() > 0.0f) + { + *trantype = GOAL_TRAN_PUSH; + nextgoal = NPC_GOAL_WANDER; + } + } + + if (*trantype != GOAL_TRAN_NONE) + { + return nextgoal; + } + + if (flg_user != 0) + { + DoAutoAnim(NPC_GSPOT_START, 0); + flg_user = 0; + } + + npc->tmr_fidget = (-1.0f > (npc->tmr_fidget - dt)) ? -1.0f : (npc->tmr_fidget - dt); + + return xGoal::Process(trantype, dt, updCtxt, scene); } -U8 xNPCBasic::ColChkByFlags() const +S32 zNPCGoalIdle::NPCMessage(NPCMsg* mail) { - return 0; + S32 handled = 0; + + switch (mail->msgid) + { + case NPC_MID_BECOMESCARED: + case NPC_MID_NOLONGERSCARED: + { + zNPCGoalCommon* goal = (zNPCGoalCommon*)psyche->GetCurGoal(); + if (goal != NULL) + { + goal->DoAutoAnim(NPC_GSPOT_RESUME, 0); + } + handled = 0; + break; + } + } + + return handled; } -U8 xNPCBasic::ColPenFlags() const +S32 zNPCGoalPatrol::Enter(F32 dt, void* updCtxt) { - return 0; + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + flg_patrol = 0; + + if (npc->nav_dest == NULL) + { + DoOnArriveStuff(); + } + else + { + Chk_AutoSmooth(); + } + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalPatrol::Exit(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + if (npc->spl_mvptspline != NULL) + { + npc->nav_dest = npc->nav_curr; + npc->nav_lead = npc->nav_curr; + npc->spl_mvptspline = NULL; + npc->len_mvptspline = 0.0f; + npc->dst_curspline = 0.0f; + } + + if (flg_patrol & (1 << 2)) + { + if (npc->nav_dest != NULL) + { + Chk_AutoSmooth(); + } + flg_patrol &= ~(1 << 2); + } + + return xGoal::Exit(dt, updCtxt); } -U8 xNPCBasic::ColChkFlags() const +S32 zNPCGoalPatrol::Resume(F32 dt, void* updCtxt) { - return 0; + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + if (flg_patrol & (1 << 2)) + { + if (npc->nav_dest != NULL) + { + Chk_AutoSmooth(); + } + flg_patrol &= ~(1 << 2); + } + + return xGoal::Resume(dt, updCtxt); +} + +S32 zNPCGoalPatrol::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + S32 nextgoal = 0; + + if (flg_patrol & (1 << 0)) + { + if (flg_patrol & (1 << 1)) + { + npc->VelStop(); + tmr_wait = (-1.0f > (tmr_wait - dt)) ? -1.0f : (tmr_wait - dt); + if (tmr_wait < 0.0f) + { + if (npc->nav_dest == NULL && npc->MvptCycle() == 0) + { + if (npc->nav_curr == NULL) + { + tmr_wait = 300.0f; + } + else + { + tmr_wait = npc->nav_curr->Delay(); + } + + tmr_wait = (2.0f > tmr_wait) ? 2.0f : tmr_wait; + } + else + { + flg_patrol &= ~(1 << 1); + DoAutoAnim(NPC_GSPOT_RESUME, 0); + } + } + } + + if (!(flg_patrol & (1 << 1))) + { + PickTransition(&nextgoal, trantype); + if (*trantype != GOAL_TRAN_NONE) + { + return nextgoal; + } + flg_patrol &= ~(1 << 0); + } + } + + if (!(flg_patrol & (1 << 1))) + { + if (npc->spl_mvptspline != NULL) + { + MoveSpline(dt); + } + else if (flg_patrol & (1 << 3)) + { + MoveAutoSmooth(dt); + } + else if (npc->nav_dest != NULL) + { + MoveNormal(dt); + } + } + + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +void zNPCGoalPatrol::DoOnArriveStuff() +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + if (npc->nav_dest != NULL) + { + zEntEvent(npc, npc->nav_dest, eEventArrive); + } + + flg_patrol |= (1 << 0); + flg_patrol &= ~(1 << 3); + + npc->MvptCycle(); + if (npc->nav_curr != NULL && npc->nav_curr->Delay() > 0.0f && + npc->nav_curr->RadiusZone() < 0.25f) + { + tmr_wait = npc->nav_curr->Delay(); + flg_patrol |= (1 << 1); + DoAutoAnim(NPC_GSPOT_PATROLPAUSE, 0); + } + else + { + Chk_AutoSmooth(); + } +} + +void zNPCGoalPatrol::PickTransition(S32* goal, en_trantype* trantype) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + if (npc->npcset.allowWander && npc->nav_curr != NULL && npc->nav_curr->Delay() > 0.0f && + npc->nav_curr->RadiusZone() > 0.0f) + { + *goal = NPC_GOAL_WANDER; + *trantype = GOAL_TRAN_PUSH; + flg_patrol |= (1 << 2); + flg_patrol &= ~(1 << 0); + } + else if (npc->nav_dest == NULL) + { + *goal = NPC_GOAL_IDLE; + *trantype = GOAL_TRAN_SET; + } +} + +// Nonmatching: nowhere near finished +#if 0 +void zNPCGoalPatrol::MoveNormal(F32 dt) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + if (npc->DBG_IsNormLog(eNPCDCAT_Eleven, -1)) + { + } +} +#endif + +S32 zNPCGoalFidget::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + + npc->VelStop(); + if (npc->drv_data == NULL || (npc->drv_data->driver == NULL && npc->drv_data->odriver == NULL)) + { + npc->flags2.flg_colCheck = 0; + npc->flags2.flg_penCheck = 0; + npc->pflags &= ~((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); + } + + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalFidget::Exit(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = (zNPCCommon*)psyche->clt_owner; + npc->RestoreColFlags(); + + return zNPCGoalPushAnim::Enter(dt, updCtxt); } diff --git a/src/SB/Game/zNPCGoalStd.h b/src/SB/Game/zNPCGoalStd.h index 3658dadf..347fe623 100644 --- a/src/SB/Game/zNPCGoalStd.h +++ b/src/SB/Game/zNPCGoalStd.h @@ -75,8 +75,112 @@ struct zNPCGoalLoopAnim : zNPCGoalCommon U32 origAnimFlags; U32 animWeMolested; - // void* __ct(S32 myType); - void LoopCountSet(S32 unk); // return type might be wrong + zNPCGoalLoopAnim(S32 myType) : zNPCGoalCommon(myType) + { + SetFlags(1 << 1); + } + + void MolestLoopAnim(); + void UnmolestAnim(); + void LoopCountSet(S32 num); + void UseDefaultAnims(); + void ValidateStages(); + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +struct zNPCGoalIdle : zNPCGoalCommon +{ + S32 flg_idle; + + zNPCGoalIdle(S32 myType) : zNPCGoalCommon(myType) + { + SetFlags((1 << 3) | (1 << 2)); + flg_npcgauto &= ~((1 << 2) | (1 << 1)); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Suspend(F32 dt, void* updCtxt); + virtual S32 Resume(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalWaiting : zNPCGoalLoopAnim +{ + S32 flg_waiting; + F32 tmr_waiting; + + zNPCGoalWaiting(S32 myType) : zNPCGoalLoopAnim(myType) + { + } +}; + +struct zNPCGoalWander : zNPCGoalCommon +{ + S32 flg_wand; + F32 tmr_remain; + F32 rad_wand; + xVec3 pos_home; + F32 tmr_minwalk; + F32 tmr_newdir; + xVec3 dir_cur; + + zNPCGoalWander(S32 myType) : zNPCGoalCommon(myType) + { + SetFlags((1 << 2) | (1 << 1)); + flg_wand = 0xFFFF0000; + } +}; + +struct zNPCGoalPatrol : zNPCGoalCommon +{ + S32 flg_patrol; + F32 tmr_wait; + xVec3 pos_midpnt[4]; + S32 idx_midpnt; + + zNPCGoalPatrol(S32 myType) : zNPCGoalCommon(myType) + { + SetFlags((1 << 2) | (1 << 1)); + } + + void DoOnArriveStuff(); + void PickTransition(S32* goal, en_trantype* trantype); + void MoveNormal(F32 dt); + void MoveSpline(F32 dt); + void Chk_AutoSmooth(); + void MoveAutoSmooth(F32 dt); + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Resume(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +struct zNPCGoalPushAnim : zNPCGoalCommon +{ + S32 flg_pushanim; + F32 lastAnimTime; + + zNPCGoalPushAnim(S32 myType) : zNPCGoalCommon(myType) + { + SetFlags((1 << 2) | (1 << 1)); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Resume(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +struct zNPCGoalFidget : zNPCGoalPushAnim +{ + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); }; struct zNPCGoalTaunt : zNPCGoalLoopAnim @@ -189,15 +293,6 @@ struct zNPCGoalAlertFodBzzt : zNPCGoalCommon void GetInArena(F32 dt); }; -struct zNPCGoalPushAnim : zNPCGoalCommon -{ - S32 flg_pushanim; - F32 lastAnimTime; - - // void* __ct(S32 myType); - S32 Enter(F32 dt, void* updCtxt); -}; - struct zNPCGoalAttackFodder; struct CattleNotify : HAZNotify @@ -264,7 +359,11 @@ struct zNPCGoalDead : zNPCGoalCommon virtual S32 Enter(F32 dt, void* updCtxt); virtual S32 Exit(F32 dt, void* updCtxt); - void DieQuietly(); + void DieQuietly() + { + flg_deadinfo |= (1 << 0); + flg_deadinfo &= ~(1 << 1); + } void DieWithAWhimper(); void DieWithABang(); diff --git a/src/SB/Game/zNPCGoalTiki.cpp b/src/SB/Game/zNPCGoalTiki.cpp index 5a983ca1..e8d17eab 100644 --- a/src/SB/Game/zNPCGoalTiki.cpp +++ b/src/SB/Game/zNPCGoalTiki.cpp @@ -7,11 +7,6 @@ #include "xEvent.h" #include "zNPCTypes.h" -extern F32 _836_0; -extern F32 _837_3; -extern F32 _862_2; -extern F32 _863_1; - xFactoryInst* GOALCreate_Tiki(S32 who, RyzMemGrow* grow, void*) { xGoal* goal; @@ -64,11 +59,11 @@ S32 zNPCGoalTikiIdle::Enter(F32, void*) if (tiki->SelfType() == NPC_TYPE_TIKI_THUNDER) { - tmr_wait = _836_0; + tmr_wait = 0.1f; } else if (!tiki->nav_dest) { - tmr_wait = _837_3; + tmr_wait = 2.0f; } else { @@ -112,10 +107,10 @@ S32 zNPCGoalTikiCount::Enter(F32, void*) { zNPCTiki* tiki = (zNPCTiki*)GetOwner(); - tmr_count = _862_2; + tmr_count = 3.0f; beingCarried = 0; - tiki->t1 = _863_1; + tiki->t1 = 0.0f; return 0; } diff --git a/src/SB/Game/zNPCGoalVillager.cpp b/src/SB/Game/zNPCGoalVillager.cpp index a3901afb..7d546c6f 100644 --- a/src/SB/Game/zNPCGoalVillager.cpp +++ b/src/SB/Game/zNPCGoalVillager.cpp @@ -1,9 +1,91 @@ #include +#include "xMath.h" +#include "xutil.h" +#include "zEntPickup.h" +#include "zGameExtras.h" #include "zGlobals.h" #include "zNPCGoalVillager.h" +#include "zNPCTypeVillager.h" +#include "zNPCGoals.h" +#include "zGoo.h" +#include "zSurface.h" -extern zGlobals globals; +xFactoryInst* GOALCreate_Villager(S32 who, RyzMemGrow* grow, void*) +{ + xGoal* goal = NULL; + + switch (who) + { + case NPC_GOAL_PLAYERNEAR: + goal = new (who, grow) zNPCGoalPlayerNear(who); + break; + case NPC_GOAL_TALK: + goal = new (who, grow) zNPCGoalTalk(who); + break; + case NPC_GOAL_CHATTER: + goal = new (who, grow) zNPCGoalChatter(who); + break; + case NPC_GOAL_SPEAK: + goal = new (who, grow) zNPCGoalSpeak(who); + break; + case NPC_GOAL_CHEER: + goal = new (who, grow) zNPCGoalCheer(who); + break; + case NPC_GOAL_HURT: + goal = new (who, grow) zNPCGoalHurt(who); + break; + case NPC_GOAL_BALLOON: + goal = new (who, grow) zNPCGoalBalloon(who); + break; + case NPC_GOAL_BOYRIDE: + goal = new (who, grow) zNPCGoalBoyRide(who); + break; + case NPC_GOAL_BOYFALL: + goal = new (who, grow) zNPCGoalBoyFall(who); + break; + case NPC_GOAL_BOYWEEP: + goal = new (who, grow) zNPCGoalBoyWeep(who); + break; + case NPC_GOAL_BOYSWIM: + goal = new (who, grow) zNPCGoalBoySwim(who); + break; + default: + xUtil_idtag2string(who, 0); + break; + } + + return goal; +} + +S32 zNPCGoalPlayerNear::NPCMessage(NPCMsg* mail) +{ + S32 handled = 0; + + switch (mail->msgid) + { + case NPC_MID_TALKSTART: + if (stat == GOAL_STAT_PROCESS) + { + handled = 1; + flg_plyrnear |= (1 << 0); + } + break; + } + + return handled; +} + +void zNPCGoalPlayerNear::ChkCheatMedic() +{ + static S32 cnt_nextMedic = 0; + cnt_nextMedic--; + if (cnt_nextMedic <= 0) + { + cnt_nextMedic = (S32)(5.0f * xurand()) + 5; + zEntPlayer_GiveHealth(1); + } +} void zNPCGoalPlayerNear::DoCheatPanHandle() { @@ -12,3 +94,454 @@ void zNPCGoalPlayerNear::DoCheatPanHandle() globals.player.Inv_Shiny -= 500; } } + +void zNPCGoalPlayerNear::ChkCheatDogTrix(S32* goal, en_trantype* trantype) +{ + // clang-format off + static U32 hashes_sc[] = { + xStrHash("LassoSwing"), + xStrHash("SlipIdle01"), + xStrHash("LCopter01"), + xStrHash("LCopterHeadUp01"), + xStrHash("TailSlide01"), + xStrHash("TailSlideJumpStart01"), + xStrHash("TailSlideJumpApex01"), + xStrHash("TailSlideFall01"), + xStrHash("TailSlideLand01"), + xStrHash("TailSlideDJumpApex01"), + }; + + static U32 hashes_ss[] = { + xStrHash("DJumpStart01"), + xStrHash("DJumpApex01"), + xStrHash("BBounceStrike01"), + 0, + 0, + }; + + static U32 hashes_pa[] = { + xStrHash("DJumpStart01"), + xStrHash("DJumpApex01"), + xStrHash("StunLand"), + }; + // clang-format on + + U32 id = globals.player.ent.model->Anim->Single->State->ID; + S32 match = 0; + if (gCurrentPlayer == eCurrentPlayerSpongeBob) + { + for (U32 i = 0; i < 5; i++) + { + if (id == hashes_ss[i]) + { + match = 1; + break; + } + } + } + else if (gCurrentPlayer == eCurrentPlayerPatrick) + { + for (U32 i = 0; i < 3; i++) + { + if (id == hashes_pa[i]) + { + match = 1; + break; + } + } + } + else if (gCurrentPlayer == eCurrentPlayerSandy) + { + for (U32 i = 0; i < 10; i++) + { + if (id == hashes_sc[i]) + { + match = 1; + break; + } + } + } + + if (match != 0) + { + static const U32 shinies[] = { 4, 3, 2, 1, 4 }; + + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + zEntPickup_SpawnNRewards((U32*)shinies, 5, npc->Center()); + *goal = NPC_GOAL_CHEER; + *trantype = GOAL_TRAN_PUSH; + } +} + +S32 zNPCGoalTalk::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + + sfx_curTalk = NULL; + aid_curSound = 0; + killAndExit = 0; + stopTalking = 0; + StartSFX(sfx_curTalk); + + if (npc->converse == NULL) + { + npc->FindMyConverse(); + } + if (npc->converse != NULL) + { + npc->hithere.npc = npc; + npc->converse->set_callback(&npc->hithere); + npc->converse->start_talk(npc); + } + npc->WonderOfTalking(1, NULL); + tmr_minTalk = 0.25f; + + xVec3Copy(&pos_maintain, xEntGetPos(npc)); + + tmr_cycleAnim = 5.0f * (0.25f * (xurand() - 0.5f)) + 5.0f; + + npc->pflags &= (U8) ~(1 << 2); + + npc->VelStop(); + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalTalk::Exit(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->WonderOfTalking(0, NULL); + npc->RestoreColFlags(); + + return xGoal::Enter(dt, updCtxt); +} + +S32 zNPCGoalTalk::NPCMessage(NPCMsg* mail) +{ + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_DAMAGE: + break; + case NPC_MID_TALKON: + killAndExit = 0; + stopTalking = 0; + break; + case NPC_MID_TALKOFF: + killAndExit = 1; + break; + default: + handled = 0; + break; + } + + return handled; +} + +void zNPCGoalTalk::StartSFX(xSFX* sfx) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + + U32 sid = 0; + if (sfx != NULL && sfx_curTalk != NULL) + { + npc->SndPlayFromSFX(sfx, &sid); + } +} + +S32 zNPCGoalSpeak::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->WonderOfTalking(1, NULL); + xVec3Copy(&pos_maintain, xEntGetPos(npc)); + tmr_cycleAnim = 5.0f * (0.25f * (xurand() - 0.5f)) + 5.0f; + npc->pflags &= (U8) ~(1 << 2); + npc->VelStop(); + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalSpeak::Exit(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->WonderOfTalking(0, NULL); + npc->RestoreColFlags(); + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalSpeak::NPCMessage(NPCMsg* mail) +{ + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_SYSEVENT: + if (mail->sysevent.toEvent == eEventNPCSetActiveOff) + { + handled = 0; + } + break; + default: + handled = 1; + break; + } + + return handled; +} + +S32 zNPCGoalCheer::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->SndPlayRandom(NPC_STYP_CHEERING); + + return zNPCGoalLoopAnim::Enter(dt, updCtxt); +} + +// Equivalent: regalloc +S32 zNPCGoalCheer::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + xVec3 *npc_pos, *player_pos; + + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + xVec3 dir_plyr = {}; + npc_pos = xEntGetPos(npc); + player_pos = xEntGetPos(&globals.player.ent); + xVec3Sub(&dir_plyr, player_pos, npc_pos); + F32 distance = xVec3Length(&dir_plyr); + + if (distance > 0.25f) + { + xVec3SMulBy(&dir_plyr, 1.0f / distance); + npc->TurnToFace(dt, &dir_plyr, -1.0f); + } + + npc->VelStop(); + + return zNPCGoalLoopAnim::Process(trantype, dt, updCtxt, scene); +} + +S32 zNPCGoalHurt::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->SndPlayRandom(NPC_STYP_EXCLAIM); + + ChkRewardCheat(); + + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalHurt::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->VelStop(); + + return zNPCGoalPushAnim::Process(trantype, dt, updCtxt, scene); +} + +void zNPCGoalHurt::ChkRewardCheat() +{ + static const U32 shinies[] = { 4, 2, 1 }; + + if (zGameExtras_CheatFlags() & (1 << 20)) + { + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + zEntPickup_SpawnNRewards((U32*)shinies, 3, npc->Center()); + } +} + +S32 zNPCGoalBalloon::Enter(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->specialBalloon = 1; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBalloon::Exit(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->specialBalloon = 0; + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalBalloon::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + + S32 nextgoal; + if (npc->plat_balloons != NULL) + { + *trantype = GOAL_TRAN_PUSH; + nextgoal = NPC_GOAL_BOYRIDE; + } + else + { + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOYFALL; + } + + // This is always true + if (*trantype != GOAL_TRAN_NONE) + { + return nextgoal; + } + + if (nextgoal != 0) + { + return nextgoal; + } + + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +S32 zNPCGoalBalloon::NPCMessage(NPCMsg* mail) +{ + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_SYSEVENT: + if (mail->sysevent.toEvent != eEventNPCSpecial_PlatformFall && + mail->sysevent.toEvent != eEventNPCSpecial_PlatformSnap) + { + handled = 0; + } + break; + case NPC_MID_DAMAGE: + handled = 1; + break; + default: + handled = 0; + break; + } + + return handled; +} + +S32 zNPCGoalBoyRide::Enter(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->flags2.flg_colCheck = 0; + npc->flags2.flg_penCheck = 0; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBoyRide::Exit(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->RestoreColFlags(); + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalBoyRide::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + S32 nextgoal = 0; + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + if (npc->plat_balloons == NULL) + { + *trantype = GOAL_TRAN_SWAP; + nextgoal = NPC_GOAL_BOYFALL; + } + + if (nextgoal != 0) + { + return nextgoal; + } + + xVec3Copy(&npc->frame->mat.pos, xEntGetPos(npc->plat_balloons)); + xMat3x3Copy((xMat3x3*)&npc->frame->mat, (xMat3x3*)npc->plat_balloons->model->Mat); + + npc->frame->mode |= 0x41; + + npc->PlatAnimSync(); + + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +S32 zNPCGoalBoyRide::NPCMessage(NPCMsg* mail) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_SYSEVENT: + if (mail->sysevent.toEvent == eEventNPCSpecial_PlatformFall) + { + npc->plat_balloons = NULL; + } + else + { + handled = 0; + } + break; + case NPC_MID_DAMAGE: + DoAutoAnim(NPC_GSPOT_ALTA, 0); + npc->PlatAnimSet(BBOY_PLATANIM_HIT); + break; + default: + handled = 0; + break; + } + + return handled; +} + +// Equivalent(???) +S32 zNPCGoalBoyFall::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + S32 nextgoal = 0; + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + + if (hitGround != 0) + { + xAnimState* anim_state = npc->AnimCurState(); + if (npc->AnimTimeRemain(anim_state) < dt + 0.001f) + { + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOYWEEP; + } + else if (anim_state->ID != anid_played) + { + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOYWEEP; + } + } + + if (nextgoal != 0) + { + return nextgoal; + } + + F32 fVar2 = -(dt * 10.0f - npc->frame->vel.y); + npc->frame->vel.y = (fVar2 > -4.0f) ? fVar2 : -4.0f; + + npc->colFreq = (npc->colFreq < 0) ? npc->colFreq : 0; + + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +S32 zNPCGoalBoyWeep::Enter(F32 dt, void* updCtxt) +{ + tmr_weep = 300.0f * (0.25f * (xurand() - 0.5f)) + 300.0f; + ang_spinrate = 0.0f; + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +// Equivalent: branching weirdness +S32 zNPCGoalBoyWeep::NPCMessage(NPCMsg* mail) +{ + if (mail->msgid == NPC_MID_DAMAGE && mail->infotype == NPC_MDAT_DAMAGE && + mail->dmgdata.dmg_type == DMGTYP_SIDE) + { + ang_spinrate += 16.0f; + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->SndPlayRandom(NPC_STYP_EXCLAIM); + } + return 0; +} diff --git a/src/SB/Game/zNPCGoalVillager.h b/src/SB/Game/zNPCGoalVillager.h index 6ee24141..bbb0da4c 100644 --- a/src/SB/Game/zNPCGoalVillager.h +++ b/src/SB/Game/zNPCGoalVillager.h @@ -1,12 +1,170 @@ #ifndef ZNPCGOALVILLAGER_H #define ZNPCGOALVILLAGER_H +#include "xSFX.h" +#include "zNPCGlyph.h" #include "zNPCGoalCommon.h" +#include "zNPCGoalStd.h" -class zNPCGoalPlayerNear +struct zNPCGoalCheer : zNPCGoalLoopAnim { -public: + zNPCGoalCheer(S32 goalID) : zNPCGoalLoopAnim(goalID) + { + SetFlags(1 << 1); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +struct zNPCGoalHurt : zNPCGoalPushAnim +{ + zNPCGoalHurt(S32 goalID) : zNPCGoalPushAnim(goalID) + { + SetFlags(1 << 1); + } + + void ChkRewardCheat(); + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +// FIXME: Put this in somewhere. +struct NPCWidget; + +struct zNPCGoalPlayerNear : zNPCGoalCommon +{ + S32 flg_plyrnear; + NPCGlyph* talk_glyph; + NPCWidget* talk_font; + F32 tmr_actBored; + + zNPCGoalPlayerNear(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags((1 << 3) | (1 << 2)); + } + + void ChkCheatMedic(); void DoCheatPanHandle(); + void ChkCheatDogTrix(S32* goal, en_trantype* trantype); + + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalTalk : zNPCGoalCommon +{ + F32 tmr_cycleAnim; + F32 tmr_minTalk; + S32 stopTalking; + S32 killAndExit; + xSFX* sfx_curTalk; + U32 aid_curSound; + xVec3 pos_maintain; + void* jawdata; + F32 jawtime; + + zNPCGoalTalk(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } + + void StartSFX(xSFX* sfx); + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalChatter : zNPCGoalCommon +{ + U32 sid_played; + U32 playThisSound; + + zNPCGoalChatter(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } +}; + +struct zNPCGoalSpeak : zNPCGoalCommon +{ + F32 tmr_cycleAnim; + xVec3 pos_maintain; + void* jawdata; + F32 jawtime; + + zNPCGoalSpeak(S32 goalID) : zNPCGoalCommon(goalID) + { + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBalloon : zNPCGoalCommon +{ + zNPCGoalBalloon(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags((1 << 3) | (1 << 2)); + AddFlags(1 << 17); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBoyRide : zNPCGoalCommon +{ + zNPCGoalBoyRide(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBoyFall : zNPCGoalCommon +{ + S32 hitGround; + + zNPCGoalBoyFall(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + flg_npcgable |= (1 << 0); + } + + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual U8 CollReview(void*); +}; + +struct zNPCGoalBoyWeep : zNPCGoalCommon +{ + F32 tmr_weep; + F32 ang_spinrate; + + zNPCGoalBoyWeep(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBoySwim : zNPCGoalCommon +{ + zNPCGoalBoySwim(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } }; xFactoryInst* GOALCreate_Villager(S32 who, RyzMemGrow* grow, void*); diff --git a/src/SB/Game/zNPCMessenger.cpp b/src/SB/Game/zNPCMessenger.cpp index ddc13af2..e479e6fd 100644 --- a/src/SB/Game/zNPCMessenger.cpp +++ b/src/SB/Game/zNPCMessenger.cpp @@ -13,3 +13,8 @@ void zNPCMsg_ScenePrepare() void zNPCMsg_Shutdown() { } + +S32 zNPCCommon::IsAlive() +{ + return 1; +} diff --git a/src/SB/Game/zNPCTypeAmbient.cpp b/src/SB/Game/zNPCTypeAmbient.cpp index b44dce59..b1cbee74 100644 --- a/src/SB/Game/zNPCTypeAmbient.cpp +++ b/src/SB/Game/zNPCTypeAmbient.cpp @@ -584,3 +584,8 @@ void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) void zNPCNeptune::SelfSetup() { } + +S32 zNPCAmbient::AmbiHandleMail(NPCMsg*) +{ + return 0; +} diff --git a/src/SB/Game/zNPCTypeAmbient.h b/src/SB/Game/zNPCTypeAmbient.h index cd331300..72946b43 100644 --- a/src/SB/Game/zNPCTypeAmbient.h +++ b/src/SB/Game/zNPCTypeAmbient.h @@ -20,6 +20,7 @@ struct zNPCAmbient : zNPCCommon virtual U8 ColChkByFlags() const; virtual U8 ColPenByFlags() const; virtual U8 PhysicsFlags(); + S32 AmbiHandleMail(NPCMsg*); }; struct zNPCJelly : zNPCAmbient diff --git a/src/SB/Game/zNPCTypeBoss.cpp b/src/SB/Game/zNPCTypeBoss.cpp index c11bb024..bef50225 100644 --- a/src/SB/Game/zNPCTypeBoss.cpp +++ b/src/SB/Game/zNPCTypeBoss.cpp @@ -11,6 +11,10 @@ U32 g_hash_bossanim[ANIM_COUNT] = {}; +void foo(zNPCBPatrick* pat) +{ +} + // clang-format off char* g_strz_bossanim[ANIM_COUNT] = { diff --git a/src/SB/Game/zNPCTypeBossPatrick.cpp b/src/SB/Game/zNPCTypeBossPatrick.cpp index a1d0ddac..d121beac 100644 --- a/src/SB/Game/zNPCTypeBossPatrick.cpp +++ b/src/SB/Game/zNPCTypeBossPatrick.cpp @@ -1,11 +1,1800 @@ -#include "xVec3.h" +#include +#include "string.h" + +#include "iModel.h" + +#include "xCollide.h" +#include "xMath.h" #include "xMath3.h" +#include "xstransvc.h" +#include "xSnd.h" +#include "xVec3.h" +#include "zCamera.h" +#include "zEntSimpleObj.h" +#include "zEntDestructObj.h" +#include "zGlobals.h" +#include "zGrid.h" #include "zNPCTypeBossPatrick.h" +#include "zRenderState.h" +#include "zNPCGoals.h" +#include "zLightning.h" +#include "zNPCTypeRobot.h" +#include -#include +#define f831 1.0f +#define f832 0.0f +#define f833 0.2f +#define f870 -1.0f +#define f875 (double)4503601774854144 // wtf? +#define f891 2.0f +#define f892 -0.4f +#define f1045 0.125f +#define f1046 0.5f +#define f1047 0.7f +#define f1048 8.0f +#define f1049 5.0f +#define f1050 2.5f +#define f1051 3.0f +#define f1052 4.2f +#define f1053 12.0f +#define f1054 6.0f +#define f1055 10.0f +#define f1056 50.0f +#define f1137 5.5f +#define f1138 6.5f +#define f1139 0.365f +#define f1140 3.1415927f +#define f1141 20.0f +#define f1142 15.0f +#define f1143 -1000000000.0f +#define f1144 1000000000.0f +#define f1656 0.0001f +#define f1657 400.0f +#define f1658 0.5775f +#define f1659 40.0f +#define f1660 -2.01f +#define f1661 0.175f +#define f1662 0.025f +#define f1663 1.25f +#define f1664 0.25f +#define f1665 80.0f +#define f1666 6.2831855f +#define f1667 3.15f +#define f1668 0.00001f +#define f1669 0.1f +#define f1670 4.0f +#define f1671 0.77f +#define f1672 0.3f +#define f1673 1.5707964f +#define f1674 0.15f +#define f1675 0.65f +#define f1676 0.75f +#define f1677 0.01f +#define f1678 0.33f +#define f1679 18.5f +#define f1680 -18.5f +#define f1681 -20.0f +#define f1682 7.0f +#define f2006 100.0f +#define f2077 5.95f +#define f2078 0.539f +#define f2215 8.5f +#define f2256 0.50049996f +#define f2257 0.45f +#define f2280 1.7f +#define f2405 -3.1415927f +#define f2423 0.4f +#define f2424 0.8f +#define f2425 1.2f +#define f2426 1.5f +#define f2427 1.8f +#define f2428 2.1f +#define f2512 0.35f +#define f2596 -0.08f +#define f2597 25.0f +#define f2610 0.6545f +#define f2629 0.7853982f +#define f2630 1.75f +#define f2696 -4.0f +#define f2697 300.0f +#define f2885 12.5f +#define f2994 7.5f + +static unsigned char sUseBossCam; +static unsigned char sWasUsingBossCam; +static unsigned char sOthersHaventBeenAdded; +static zNPCBPatrick* sPat_Ptr; +static xVec3* sCamSubTarget; +static F32 sSecsSincePatWasCarryingHead; +static xVec3 sCamSubTargetFixed; +static F32 sCurrYaw; +static F32 sCurrHeight; +static F32 sCurrRadius; +static F32 sCurrPitch; +static F32 sCurrYawOffset; +static F32 sCurrCamInterp; +static F32 minYVel; +static F32 varYVel; +static F32 minHMul; +static F32 varHMul; +static F32 minT; +static F32 varT; +static S32 sBone[10]; +static S32 sBoundBone[4]; +static F32 sBoundRadius[4]; +static xVec3 sBoneOffset[4]; +static newsfishSound sNFComment[37]; +static U32 sCurrNFSound; +static tweak_callback newsfish_cb; +static tweak_callback recenter_cb; + +void test(S32) +{ +} + +static void GetBonePos(xVec3* result, xMat4x3* matArray, S32 index, xVec3* offset) +{ +} + +static void Pat_ResetGlobalStuff() +{ +} + +void zNPCBPatrick::Init(xEntAsset* asset) +{ + /* + signed int i; // r20 + class xEnt * ent; // r19 + class RwTexture * tempTexture; // r2 + */ +} + +void on_change_newsfish(const tweak_info&) +{ + sPat_Ptr->newsfish->SpeakStart(sNFComment[sCurrNFSound].soundID, 0, -1); +} + +void on_change_recenter(const tweak_info&) +{ + sPat_Ptr->bossFlags |= 0x200; +} + +// 73% match. Kind of a difficult function +void zNPCBPatrick::Setup() +{ + char tempString[32]; // r29+0xA0 + char objName[32]; // r29+0x80 + /* + char tempString[32]; // r29+0xA0 + signed int i; // r18 + signed int j; // r20 + class RpAtomic * tempIModel; // r2 + class xMarkerAsset * marker; // r2 + char objName[32]; // r29+0x80 + */ + + this->freezeBreathEmitter = zParEmitterFind("FREEZE_BREATH_EMIT"); + this->fudgeEmitter = zParEmitterFind("FUDGE_EMIT"); + this->steamEmitter = zParEmitterFind("STEAM PAR EMIT"); + this->gooObj = (xEnt*)zSceneFindObject(xStrHash("GOO OBJ")); + this->fudgeHandle = (xEnt*)zSceneFindObject(xStrHash("FUDGE_HANDLE")); + + // + + strcpy(objName, "SWINGHOOK 00"); + this->origSwingerHeight = f832; + + for (S32 i = 0; i < 8; i++) + { + objName[11]++; + this->swinger[i] = (xEnt*)zSceneFindObject(xStrHash(objName)); + this->origSwingerHeight = + this->swinger[i]->model->Mat->pos.y * f1045 + this->origSwingerHeight; + } + + for (S32 i = 0; i < 8; i++) + { + this->swinger[i]->model->Mat->pos.y += + (this->origSwingerHeight - this->swinger[i]->model->Mat->pos.y); + } + + // + + strcpy(objName, "WOODEN_PLAT_00_00"); + + for (S32 i = 0; i < 8; i++) + { + objName[16]++; + + for (S32 j = 0; j < 3; j++) + { + objName[13]++; + this->box[j][i].box = (xEnt*)zSceneFindObject(xStrHash(objName)); + this->box[j][i].minY = this->box[j][i].box->model->Mat->pos.y; + // must be being cast to some other data type to dereference 0xd8 + // probably zEntSimpleObj? + ((zEntSimpleObj*)this->box[j][i].box)->sflags |= 8; + } + } + + this->backBox.box = (xEnt*)zSceneFindObject(xStrHash("WOODEN_PLAT_BACK")); + this->backBox.minY = f1046; + + // must be being cast to some other data type to dereference 0xd8 + // zEntDestructObj? + // zUI? + // zEntSimpleObj? + // zEGenerator? + // not exactly sure what type it is exactly, + // but it's probably zEntSimpleObj because 0xd8 is flags + ((zEntSimpleObj*)this->backBox.box)->sflags |= 8; + + this->boxBreak = (zShrapnelAsset*)xSTFindAsset(xStrHash("b2_box_shrapnel"), NULL); + this->boxSplash = (zShrapnelAsset*)xSTFindAsset(xStrHash("b2_box_splash_shrapnel"), NULL); + this->spitModel = (RpAtomic*)xSTFindAsset(xStrHash("fx_boss_pa_spit"), NULL); + this->splatModel = (RpAtomic*)xSTFindAsset(xStrHash("fx_boss_pa_splat"), NULL); + this->shardModel = (RpAtomic*)xSTFindAsset(xStrHash("b2_ice_shard"), NULL); + this->iceBreak = (zShrapnelAsset*)xSTFindAsset(xStrHash("sb_ice_break"), NULL); + + RpAtomic* tempIModel = (RpAtomic*)xSTFindAsset(xStrHash("b2_SB_frozen"), NULL); + this->frozenSB = NULL; + this->frozenSB = (xModelInstance*)xModelInstanceAlloc(tempIModel, NULL, 0, 0, NULL); + + tempIModel = (RpAtomic*)xSTFindAsset(xStrHash("b2_SB_frozen_ice"), NULL); + this->frozenSBIce = NULL; + this->frozenSBIce = (xModelInstance*)xModelInstanceAlloc(tempIModel, NULL, 0, 0, NULL); + this->frozenSBIce->Alpha = f1047; + + this->round1Csn = (zCutsceneMgr*)zSceneFindObject(xStrHash("CSNMGR_ROUND1")); + this->round2Csn = (zCutsceneMgr*)zSceneFindObject(xStrHash("CSNMGR_ROUND2")); + this->round3Csn = (zCutsceneMgr*)zSceneFindObject(xStrHash("CSNMGR_ROUND3")); + + this->safeGroundPortal = (_zPortal*)zSceneFindObject(xStrHash("SAFEGROUND_PORTAL")); + xVec3Copy(&this->arenaExtent, (xVec3*)xSTFindAsset(xStrHash("MK ARENA EXTENT"), NULL)); + xVec3Copy(&this->fudgePos, (xVec3*)xSTFindAsset(xStrHash("FUDGE_POS"), NULL)); + xVec3Init(&this->fudgeFace, f832, f832, f831); + xVec3AddTo(&this->fudgeFace, &this->fudgePos); + + // + + strcpy(objName, "ROBOT_CHUCK_NPC01"); + + for (S32 i = 0; i < 3; i++) + { + this->chuckList[i] = (zNPCCommon*)zSceneFindObject(xStrHash(objName)); + objName[16]++; + } + + strcpy(objName, "MP_CHUCK_ARENA01"); + + for (S32 i = 0; i < 3; i++) + { + this->chuckMovePoint[i] = (zMovePoint*)zSceneFindObject(xStrHash(objName)); + objName[15]++; + } + + for (S32 i = 0; i < 3; i++) + { + ((zNPCRobot*)this->chuckList[i])->DuploOwner(this); + } + + this->newsfish = (zNPCNewsFish*)zSceneFindObject(xStrHash("NEWSFISH")); + this->newsfish->TalkOnScreen(1); + + strcpy(tempString, "HEALTH_00"); + + for (S32 i = 0; i < 2; i++) + { + this->underwear[i] = (zEntPickup*)zSceneFindObject(xStrHash(tempString)); + tempString[8]++; + } + + this->conveyorBelt[0] = (zPlatform*)zSceneFindObject(xStrHash("CONVEYOR BELT 01")); + this->conveyorBelt[1] = (zPlatform*)zSceneFindObject(xStrHash("CONVEYOR BELT 02")); + this->conveyorBelt[2] = (zPlatform*)zSceneFindObject(xStrHash("CONVEYOR BELT 03")); + this->conveyorBelt[3] = (zPlatform*)zSceneFindObject(xStrHash("CONVEYOR BELT 04")); + this->conveyorBelt[4] = (zPlatform*)zSceneFindObject(xStrHash("CONVEYOR BELT 08")); + this->conveyorBelt[5] = (zPlatform*)zSceneFindObject(xStrHash("CONVEYOR BELT 09")); + this->conveyorBelt[6] = (zPlatform*)zSceneFindObject(xStrHash("CONVEYOR BELT 10")); + + this->bossCam.cfg.zone_rest.distance = f1048; + this->bossCam.cfg.zone_rest.height = f1049; + this->bossCam.cfg.zone_rest.height_focus = f1050; + this->bossCam.cfg.zone_above.distance = f1051; + this->bossCam.cfg.zone_above.height = f1052; + this->bossCam.cfg.zone_above.height_focus = f870; + this->bossCam.cfg.zone_below.distance = f1053; + this->bossCam.cfg.zone_below.height = f1051; + this->bossCam.cfg.zone_below.height_focus = f1054; + this->bossCam.cfg.move_speed = f1055; + this->bossCam.cfg.turn_speed = f1055; + this->bossCam.cfg.stick_speed = f1055; + this->bossCam.cfg.stick_yaw_vel = f1055; + this->bossCam.cfg.max_yaw_vel = f1056; + this->bossCam.cfg.margin_angle = f870; + + this->bossCam.init(); + this->bossCam.add_tweaks("NPC|zNPCBPatrick|Boss Cam|"); + xDebugAddTweak("NPC|zNPCBPatrick|Boss Cam|Recenter", "*", (tweak_callback*)&recenter_cb, + (void*)0x0, 0); + + zNPCCommon::Setup(); +} + +static S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 hitCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 spitCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 runCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 smackCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 freezeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 spawnCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 spinCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 fudgeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); + +void zNPCBPatrick::SelfSetup() +{ + Pat_ResetGlobalStuff(); + + xBehaveMgr* bmgr = xBehaveMgr_GetSelf(); + this->psy_instinct = bmgr->Subscribe(this, 0); + + xPsyche* psy = this->psy_instinct; + + psy->BrainBegin(); + + xGoal* goal = psy->AddGoal(NPC_GOAL_BOSSPATIDLE, NULL); + goal->SetCallbacks(idleCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATTAUNT, NULL); + goal->SetCallbacks(tauntCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATHIT, NULL); + goal->SetCallbacks(hitCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATSPIT, NULL); + goal->SetCallbacks(spitCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATRUN, NULL); + goal->SetCallbacks(runCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATSMACK, NULL); + goal->SetCallbacks(smackCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATFREEZE, NULL); + goal->SetCallbacks(freezeCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATSPAWN, NULL); + goal->SetCallbacks(spawnCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATSPIN, NULL); + goal->SetCallbacks(spinCB, NULL, NULL, NULL); + + goal = psy->AddGoal(NPC_GOAL_BOSSPATFUDGE, NULL); + goal->SetCallbacks(fudgeCB, NULL, NULL, NULL); + + psy->BrainEnd(); + + psy->SetSafety(NPC_GOAL_BOSSPATIDLE); +} + +WEAK void xDebugAddTweak(const char*, U32*, U32, U32, const tweak_callback*, void*, U32); +void xDebugAddTweak(const char*, float*, float, float, const tweak_callback*, void*, unsigned int); + +void zNPCBPatrick::Reset() +{ + /* + signed int i; // r5 + class bossPatBox * bx; // r2 + */ + Pat_ResetGlobalStuff(); + + if (this->model) + { + if (this->model->Next) + { + if (this->model->Next->Next) + { + if (this->model->Next->Next->Next) + { + this->model->Next->Next->Next->Flags &= 0xfffe; + } + } + } + } + + sUseBossCam = 1; + sCurrHeight = f1137; + sCurrRadius = f1138; + sCurrPitch = f1139; + sCurrYaw = f1140; + zCameraDisableTracking(CO_BOSS); + sCamSubTarget = (xVec3*)&this->model->Mat->pos; + + this->bossFlags = 0x100; + gotoRound(this->round); + this->firstUpdate = true; + this->notSwingingLastFrame = true; + + S32 i = 0; + + for (i = 0; i < 50; i++) + { + this->glob[i].flags = 0; + } + + /* + for (S32 i = 2; i > 0; i++) + { + // this-> + } + */ + + this->currGlob = 0; + this->splatTimer = f832; + + for (i = 0; i < 6; i++) + { + bossPatBox* box = &this->box[0][i]; + + box->velocity = f832; + box->flags = 0; + box->pos = f1141 + this->box[0][i].minY; + } + + this->backBox.velocity = f832; + this->backBox.flags = 0; + this->backBox.pos = f1141 + (this->backBox.minY); + + this->chuckFlags[0] = 1; + this->chuckFlags[1] = 1; + this->chuckFlags[2] = 1; + + this->frozenTimer = f870; + + zEntPlayerControlOn(CONTROL_OWNER_FROZEN); + + this->csnTimer = f832; + this->nfFlags = 0; + + this->badHitTimer = f832; + this->numPCHitsInARow = 0; + this->numMissesInARow = 0; + + zNPCCommon::Reset(); + + if (this->psy_instinct) + { + this->psy_instinct->GoalSet(NPC_GOAL_BOSSPATIDLE, 0); + } + + minHMul = f1142; + minT = f1049; + minYVel = f1049; + varHMul = f832; + varT = f1049; + varYVel = f832; + + xDebugAddTweak("NPC|zNPCBPatrick|globs|minYVel", &minYVel, f1143, f1144, (tweak_callback*)0x0, + (void*)0x0, 0); + xDebugAddTweak("NPC|zNPCBPatrick|globs|varYVel", &varYVel, f1143, f1144, (tweak_callback*)0x0, + (void*)0x0, 0); + xDebugAddTweak("NPC|zNPCBPatrick|globs|minHMul", (float*)&minHMul, f1143, f1144, + (tweak_callback*)0x0, (void*)0x0, 0); + xDebugAddTweak("NPC|zNPCBPatrick|globs|varHMul", &varHMul, f1143, f1144, (tweak_callback*)0x0, + (void*)0x0, 0); + xDebugAddTweak("NPC|zNPCBPatrick|globs|minT", (float*)&minT, f1143, f1144, (tweak_callback*)0x0, + (void*)0x0, 0); + xDebugAddTweak("NPC|zNPCBPatrick|globs|varT", (float*)&varT, f1143, f1144, (tweak_callback*)0x0, + (void*)0x0, 0); + xDebugAddTweak("NPC|zNPCBPatrick|Newsfish", "Speak", (tweak_callback*)&newsfish_cb, (void*)0x0, + 0); + xDebugAddTweak("NPC|zNPCBPatrick|NewsfishComment", &sCurrNFSound, 0, 0x24, (tweak_callback*)0x0, + (void*)0x0, 0); +} + +void zNPCBPatrick::Destroy() +{ + if (this->frozenSB) + { + xModelInstanceFree(this->frozenSB); + this->frozenSB = NULL; + } + + if (this->frozenSBIce) + { + xModelInstanceFree(this->frozenSBIce); + this->frozenSBIce = NULL; + } + + zNPCCommon::Destroy(); +} + +U32 zNPCBPatrick::AnimPick(S32 rawgoal, en_NPC_GOAL_SPOT gspot, xGoal* goal) +{ + S32 index = -1; + U32 animId = 0; + + switch (rawgoal) + { + case NPC_GOAL_BOSSPATIDLE: + index = 1; + break; + case NPC_GOAL_BOSSPATTAUNT: + index = 3; + break; + case NPC_GOAL_BOSSPATHIT: + index = 7; + break; + case NPC_GOAL_BOSSPATSPIT: + { + S32 stage = ((zNPCGoalBossPatSpit*)rawgoal)->stage; + // animId = *(int*)(param_3 + 0x50); + if (stage == 0) + { + index = 0x20; + } + else if (stage == 1) + { + index = 0x21; + } + else if (stage == 2) + { + index = 0x22; + } + break; + } + case NPC_GOAL_BOSSPATRUN: + index = 4; + break; + case NPC_GOAL_BOSSPATSMACK: + index = 6; + break; + case NPC_GOAL_BOSSPATFREEZE: + index = 0x1c; + break; + case NPC_GOAL_BOSSPATSPAWN: + index = 0x23; + break; + case NPC_GOAL_BOSSPATSPIN: + { + S32 stage = ((zNPCGoalBossPatSpin*)rawgoal)->stage; + if (stage == 0) + { + index = 0x24; + } + else if (stage == 1) + { + index = 0x25; + } + else if (stage == 2) + { + index = 0x26; + } + else if (stage == 3) + { + index = 10; + } + else if (stage == 4) + { + index = 0x27; + } + else if (stage == 5) + { + index = 0x28; + } + else if (stage == 6) + { + index = 9; + } + break; + } + case NPC_GOAL_BOSSPATFUDGE: + { + S32 stage = ((zNPCGoalBossPatFudge*)rawgoal)->stage; + + if (((stage == 0) || (stage == 1)) || (stage == 2)) + { + index = 4; + } + else if ((stage == 3) || (stage == 4)) + { + index = 0x1d; + } + else if (stage == 5) + { + index = 0x1e; + } + else if (stage == 6) + { + index = 0x1f; + } + break; + } + default: + index = 1; + break; + } + + if (index > -1) + { + animId = g_hash_bossanim[index]; + } + + return animId; +} + +void zNPCBPatrick::Process(xScene* xscn, F32 dt) +{ + /* + signed int i; // r5 + signed int j; // r21 + signed int csn; // r17 + float fudgeRate; // r1 + float * swingY; // r4 + signed int shouldPlayIt; // r3 + float finalHeight; // r2 + class xModelInstance * tempModel; // r19 + float maxDist; // r28 + float numSnowflakes; // r27 + float currSize; // r26 + class xVec3 snowDir; // r29+0x170 + class xVec3 snowPos; // r29+0x160 + signed int numSamples; // r20 + float interp; // r25 + signed int numToEmit; // r19 + float theta; // r21 + float moveSplat; // r20 + float timeTillEnd; // r1 + class xCollis colls; // r29+0xF0 + unsigned int doDamage; // r20 + class xVec3 knockback; // r29+0x150 + signed int touchDamage; // r19 + class xCollis * coll; // r6 + class xCollis * cend; // r5 + class xVec3 bubbleVel; // r29+0x140 + unsigned int picker; // r2 + signed int num; // r17 + */ +} + +void zNPCBPatrick::DuploNotice(en_SM_NOTICES note, void* data) +{ + if (note != 1) + { + return; + } + + for (S32 i = 0; i < 3; i++) + { + if (this->chuckList[i] == (zNPCCommon*)data) + { + this->chuckFlags[i] |= 1; + } + } +} + +void zNPCBPatrick::Damage(en_NPC_DAMAGE_TYPE dmg_type, xBase* who, const xVec3* vec_hit) +{ + xVec3 toHit; + + if (dmg_type == DMGTYP_SIDE || dmg_type == DMGTYP_CRUISEBUBBLE || dmg_type == DMGTYP_BUBBOWL) + { + if (this->bossFlags & 4) + { + if (vec_hit) + { + xVec3Copy(&toHit, vec_hit); + } + else + { + xVec3Sub(&toHit, (xVec3*)&this->model->Mat->pos, + (xVec3*)&globals.player.ent.model->Mat->pos); + } + + toHit.y = f832; + + xVec3Normalize(&toHit, &toHit); + + if (xVec3Dot(&toHit, (xVec3*)&this->model->Mat->at) > f832) + { + this->bossFlags |= 8; + this->badHitTimer = f1054; + } + } + else if (this->badHitTimer < f832) + { + if (this->nfFlags & 4) + { + if (xrand() & 0x80 && this->round != 2) + { + this->newsfish->SpeakStart(sNFComment[24].soundID, 0, -1); + } + else + { + this->newsfish->SpeakStart(sNFComment[25].soundID, 0, -1); + } + } + else + { + if (this->round != 2) + { + this->newsfish->SpeakStart(sNFComment[24].soundID, 0, -1); + } + else + { + this->newsfish->SpeakStart(sNFComment[25].soundID, 0, -1); + } + + this->nfFlags |= 4; + } + this->badHitTimer = f1054; + } + } +} + +void zNPCBPatrick_GameIsPaused(zScene* scn) +{ + if (sPat_Ptr && sPat_Ptr->bossFlags & 0x100) + { + sPat_Ptr->bossFlags &= 0xfffffeff; + sPat_Ptr->hiddenByCutscene(); + } +} + +// 42% +void zNPCBPatrick::RenderGlobs() +{ + /* + class xMat4x3 globMat; // r29+0xB0 + signed int i; // r29+0xA0 + */ + xMat4x3 globMat; + S32 i; + + iModelSetMaterialAlpha(this->spitModel, 215); + iModelMaterialMul(this->spitModel, f832, f831, f832); + + iModelSetMaterialAlpha(this->splatModel, 215); + iModelMaterialMul(this->splatModel, f832, f831, f832); + + for (i = 0; i < 50; i++) + { + bossPatGlob* glob = &this->glob[i]; + if (glob->flags & 1) + { + if (glob->flags & 4) + { + xVec3Copy(&globMat.pos, &glob->path.initPos); + xVec3Copy(&glob->lastPos, &globMat.pos); + xVec3Init(&globMat.at, f832, f831, f832); + globMat.right.x = -glob->path.initVel.x; + globMat.right.y = f832; + globMat.right.z = -glob->path.initVel.z; + + F32 dVar5 = xVec3Length(&globMat.up); + + if (dVar5 >= f1668) + { + xVec3SMulBy(&globMat.up, f831 / dVar5); + } + + xVec3Cross(&globMat.pos, &globMat.up, &globMat.right); + xMat3x3SMul(&globMat, &globMat, f891); + + if (!iModelCull(this->splatModel, (RwMatrix*)&globMat)) + { + iModelRender(this->splatModel, (RwMatrix*)&globMat); + } + } + else + { + xParabolaEvalPos(&glob->path, &globMat.pos, glob->t); + + if (this->gooHeight < globMat.pos.y) + { + xVec3Copy(&glob->lastPos, &globMat.pos); + xParabolaEvalVel(&glob->path, &globMat.right, glob->t); + + F32 dVar5 = xVec3Length(&globMat.up); + + if (dVar5 > f1668) + { + xVec3SMulBy(&globMat.up, f831 / dVar5); + globMat.right.x = globMat.up.x; + globMat.right.y = f832; + globMat.right.z = -globMat.up.y; + } + else + { + xVec3Init(&globMat.up, f832, f870, f832); + xVec3Init(&globMat.right, f831, f832, f832); + } + + xVec3Cross(&globMat.pos, &globMat.up, &globMat.right); + xMat3x3SMul(&globMat, &globMat, f891); + + if (!iModelCull(this->spitModel, (RwMatrix*)&globMat)) + { + iModelRender(this->spitModel, (RwMatrix*)&globMat); + } + } + } + } + } + + iModelResetMaterial(this->spitModel); + iModelResetMaterial(this->splatModel); +} + +void zNPCBPatrick::RenderFrozenPlayer() +{ + xMat4x3 globMat; + xVec3 player_pos; + + xVec3Copy(&player_pos, (xVec3*)&globals.player.ent.model->Mat->pos); + + player_pos.x = this->shakeAmp * isin(this->shakePhase) + player_pos.x; + player_pos.z = this->shakeAmp * icos(this->shakePhase) + player_pos.z; + + for (S32 i = 0; i < 10; i++) + { + if (this->shard[i].size > f832) + { + xMat3x3Rot(&globMat, &this->shard[i].rotVec, this->shard[i].ang); + xVec3Copy(&globMat.pos, &player_pos); + xMat3x3SMul(&globMat, &globMat, this->shard[i].size); + if (!iModelCull(this->shardModel, (RwMatrixTag*)&globMat)) + { + F32 ivar1 = f2006 * ((f831 - this->shard[i].maxSize) + this->shard[i].size); + iModelSetMaterialAlpha(this->shardModel, ivar1); + iModelRender(this->shardModel, (RwMatrix*)&globMat); + } + } + } + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1); + + if (this->frozenSB) + { + // I don't think Mat->right here is necessarily correct + // It looks like it should just be Mat + xMat4x3Copy((xMat4x3*)&this->frozenSB->Mat->right, + (xMat4x3*)&globals.player.ent.model->Mat->right); + xModelRender(this->frozenSB); + } + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)2); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0); + + if (this->frozenSBIce) + { + xMat4x3Copy((xMat4x3*)&this->frozenSBIce->Mat->right, + (xMat4x3*)&globals.player.ent.model->Mat->right); + xModelRender(this->frozenSBIce); + } +} + +void zNPCBPatrick::RenderExtra() +{ + zNPCCommon::RenderExtra(); + + _SDRenderState oldState = zRenderStateCurrent(); + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)2); + + this->RenderGlobs(); + + if (this->bossFlags & 0x10) + { + this->RenderFrozenPlayer(); + } + + zRenderState(SDRS_Default); + zRenderState(oldState); +} + +void zNPCBPatrick::NewTime(xScene* xscn, F32 dt) +{ + // signed int i; // r20 + + for (S32 i = 0; i < 4; i++) + { + if (sBoundRadius[i] > f832) + { + GetBonePos(&this->boundList[i]->bound.box.center, (xMat4x3*)&this->model->Mat, + sBone[sBoundBone[i]], &sBoneOffset[i]); + + xQuickCullForBound(&this->boundList[i]->bound.qcd, &this->boundList[i]->bound); + zGridUpdateEnt(this->boundList[i]); + } + } + + zNPCCommon::NewTime(xscn, dt); +} + +S32 zNPCBPatrick::nextGoal() +{ + S32 nextgoal = 0; + + if (this->bossFlags & 0x100) + { + return NPC_GOAL_BOSSPATIDLE; + } + + if (this->bossFlags & 2) + { + return NPC_GOAL_BOSSPATTAUNT; + } + + nextgoal = this->task[this->currTask]; + this->currTask++; + + if (this->currTask >= this->numTasks) + { + this->currTask = 0; + } + + if (nextgoal == NPC_GOAL_BOSSPATSPAWN && !this->canSpawnChucks()) + { + nextgoal = this->nextGoal(); + } + + return nextgoal; +} + +// not in PS2 dwarf +bossPatGlob* zNPCBPatrick::getNextFreeGlob() +{ + bossPatGlob* glob = &this->glob[this->currGlob]; + + this->currGlob++; + + if (this->currGlob >= 50) + { + this->currGlob = 0; + } + + glob->flags = 1; + return glob; +} + +void zNPCBPatrick::playSplat(xVec3* pos) +{ + // float picker; // r2 +} + +U32 zNPCBPatrick::canSpawnChucks() +{ + U32 result = 0; + + for (S32 i = 0; i < 3; i++) + { + if (this->chuckFlags[i] & 1) + { + result = 1; + break; + } + } + + return result; +} + +void zNPCBPatrick::gotoRound(S32 num) +{ + this->round = num; + + switch (this->round) + { + case 1: + { + this->numTasks = 12; + this->task[0] = NPC_GOAL_BOSSPATIDLE; + this->task[1] = NPC_GOAL_BOSSPATSMACK; + this->task[2] = NPC_GOAL_BOSSPATIDLE; + this->task[3] = NPC_GOAL_BOSSPATSPIT; + this->task[4] = NPC_GOAL_BOSSPATIDLE; + this->task[5] = NPC_GOAL_BOSSPATSPIN; + this->task[6] = NPC_GOAL_BOSSPATIDLE; + this->task[7] = NPC_GOAL_BOSSPATSMACK; + this->task[8] = NPC_GOAL_BOSSPATIDLE; + this->task[9] = NPC_GOAL_BOSSPATSPIT; + this->task[10] = NPC_GOAL_BOSSPATIDLE; + this->task[11] = NPC_GOAL_BOSSPATSPIN; + this->currTask = 0; + this->hitPoints = 9; + this->gooLevel = 0; + this->gooHeight = this->gooLevel - f1046; + break; + } + case 2: + { + this->numTasks = 8; + this->task[0] = NPC_GOAL_BOSSPATIDLE; + this->task[1] = NPC_GOAL_BOSSPATSPIT; + this->task[2] = NPC_GOAL_BOSSPATIDLE; + this->task[3] = NPC_GOAL_BOSSPATSPIN; + this->task[4] = NPC_GOAL_BOSSPATIDLE; + this->task[5] = NPC_GOAL_BOSSPATSPIT; + this->task[6] = NPC_GOAL_BOSSPATIDLE; + this->task[7] = NPC_GOAL_BOSSPATSPIN; + this->currTask = 0; + this->hitPoints = 6; + this->gooLevel = 0; + this->gooHeight = this->gooLevel - f1046; + break; + } + case 3: + { + this->numTasks = 10; + this->task[0] = NPC_GOAL_BOSSPATIDLE; + this->task[1] = NPC_GOAL_BOSSPATFREEZE; + this->task[2] = NPC_GOAL_BOSSPATSPIT; + this->task[3] = NPC_GOAL_BOSSPATIDLE; + this->task[4] = NPC_GOAL_BOSSPATSPIN; + this->task[5] = NPC_GOAL_BOSSPATIDLE; + this->task[6] = NPC_GOAL_BOSSPATFREEZE; + this->task[7] = NPC_GOAL_BOSSPATSPIT; + this->task[8] = NPC_GOAL_BOSSPATIDLE; + this->task[9] = NPC_GOAL_BOSSPATSPIN; + this->currTask = 0; + this->hitPoints = 3; + this->gooLevel = 3; + break; + } + case 4: + { + zEntEvent(this, 36); + this->numTasks = 1; + this->task[0] = NPC_GOAL_BOSSPATIDLE; + this->currTask = 0; + this->hitPoints = 0; + this->gooLevel = 3; + break; + } + } +} + +// I think xPlatformAsset type might not be correct +// WIP +F32 zNPCBPatrick::ConveyorTimeLeft(zPlatform* platform, xVec3* vec_unk) +{ + xVec3 output; + + F32 fVar1; + + if (platform->passet->pad > f832) + { + fVar1 = platform->bound.box.center.x; + } + else + { + fVar1 = platform->bound.box.center.y; + } + + xVec3Sub(&output, vec_unk, &platform->bound.box.center); + F32 dVar3 = xVec3Dot(&output, &platform->bound.box.center); + F32 dVar4 = xVec3Length2(&platform->bound.box.center); + + return fVar1 - dVar3 / dVar4 / platform->passet->pad; +} + +void zNPCBPatrick::ParabolaHitsConveyors(xParabola* path, xCollis* colls) +{ + /* + signed int i; // r13 + signed int j; // r12 + class xMat4x3 * mat; // r11 + class xVec3 * lower; // r10 + class xVec3 * upper; // r9 + float a; // r10 + float b; // r9 + float det; // r4 + float t[2]; // r29+0x18 + float dispX; // r11 + float dispZ; // r8 + */ +} + +// return type probably wrong. not in PS2 dwarf +void zNPCBPatrick::bossPatBoxCheckCollide(bossPatBox* bx) +{ +} + +void zNPCBPatrick::bossPatBoxUpdate(bossPatBox* bx, F32 dt) +{ +} + +static S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossPatIdle* idle = (zNPCGoalBossPatIdle*)rawgoal; + zNPCBPatrick* pat = (zNPCBPatrick*)idle->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + return 0; + } + + if (pat->bossFlags & 2) + { + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOSSPATTAUNT; + } + else if (idle->timeInGoal > f1676 && idle->timeInGoal > f891) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossPatTaunt* taunt = (zNPCGoalBossPatTaunt*)rawgoal; + zNPCBPatrick* pat = (zNPCBPatrick*)taunt->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (pat->AnimTimeRemain(NULL) < f2280 * dt) + { + pat->bossFlags &= 0xfffffffd; + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 hitCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossPatHit* hit = (zNPCGoalBossPatHit*)rawgoal; + zNPCBPatrick* pat = (zNPCBPatrick*)hit->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (pat->AnimTimeRemain(NULL) < f2280 * dt) + { + if (pat->round == 2) + { + nextgoal = NPC_GOAL_BOSSPATFUDGE; + *trantype = GOAL_TRAN_SET; + } + else + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + } + + return nextgoal; +} + +static S32 spitCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossPatSpit* spit = (zNPCGoalBossPatSpit*)rawgoal; + zNPCBPatrick* pat = (zNPCBPatrick*)spit->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if ((spit->stage == 1 || spit->stage == 2) && pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 runCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)rawgoal->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 smackCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)rawgoal->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 freezeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)rawgoal->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 spawnCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossPatSpawn* spawn = (zNPCGoalBossPatSpawn*)rawgoal; + zNPCBPatrick* pat = (zNPCBPatrick*)rawgoal->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (spawn->stage == 3 && pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +// This function was a PITA to match +static S32 spinCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossPatSpin* spin = (zNPCGoalBossPatSpin*)rawgoal; + zNPCBPatrick* pat = (zNPCBPatrick*)rawgoal->GetOwner(); + S32 nextgoal = 0; + + if (globals.player.ControlOff & 0xffffbaff) + { + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (spin->stage == 6) + { + if (pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + } + else if (spin->stage == 2 && pat->bossFlags & 2) + { + if (pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = NPC_GOAL_BOSSPATTAUNT; + *trantype = GOAL_TRAN_SET; + } + } + else if (pat->bossFlags & 4 && pat->bossFlags & 8) + { + pat->hitPoints--; + zEntEvent(pat, pat, 471); + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOSSPATHIT; + + if (!(pat->nfFlags & 0x800)) + { + pat->newsfish->SpeakStart(sNFComment[35].soundID, 0, -1); + pat->nfFlags |= 0x800; + } + else if (pat->numMissesInARow > 5) + { + pat->newsfish->SpeakStart(sNFComment[29].soundID, 0, -1); + pat->numMissesInARow = 0; + } + else if (pat->numPCHitsInARow > 2 || (pat->numPCHitsInARow == 2 && (xrand() & 0x80))) + { + pat->newsfish->SpeakStart(sNFComment[28].soundID, 0, -1); + } + else + { + U32 picker = xrand(); + + if (!(picker & 0x300)) + { + if (picker & 0x40) + { + pat->newsfish->SpeakStart(sNFComment[35].soundID, 0, -1); + } + else + { + pat->newsfish->SpeakStart(sNFComment[36].soundID, 0, -1); + } + } + } + + pat->numPCHitsInARow = 0; + } + + return nextgoal; +} + +static S32 fudgeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossPatFudge* fudge = (zNPCGoalBossPatFudge*)rawgoal; + zNPCBPatrick* pat = (zNPCBPatrick*)rawgoal->GetOwner(); + S32 nextgoal = 0; + + if (fudge->stage == 5 && globals.player.ControlOff & 0xffffbaff) + { + if (fudge->vomitSndID) + { + xSndStop(fudge->vomitSndID); + } + + *trantype = GOAL_TRAN_SET; + return NPC_GOAL_BOSSPATIDLE; + } + + if (fudge->stage == 6 && pat->AnimTimeRemain(NULL) < f2280 * dt) + { + nextgoal = pat->nextGoal(); + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 Pat_FaceTarget(zNPCBPatrick* pat, const xVec3* target, F32 turn_rate, F32 dt) +{ + S32 retval = -1; + xVec3 newAt; + + xVec3Sub(&newAt, target, (xVec3*)&pat->model->Mat->pos); + + newAt.y = f832; + F32 a = xVec3Normalize(&newAt, &newAt); + + F32 currRot = xatan2(pat->model->Mat->at.x, pat->model->Mat->at.z); + F32 desireRot = xatan2(newAt.x, newAt.z); + + F32 diffRot = desireRot - currRot; + + if (diffRot > f1140) + { + diffRot -= f1666; + } + + if (diffRot < f2405) + { + diffRot += f1666; + } + + F32 deltaRot = turn_rate * dt; + + if ((F32)iabs(diffRot) < deltaRot) + { + pat->frame->mat.at = newAt; + retval = 0; + } + else + { + if (diffRot < f832) + { + deltaRot = -deltaRot; + retval = 1; + } + + desireRot = currRot + deltaRot; + deltaRot = isin(currRot + deltaRot); + pat->frame->mat.at.x = deltaRot; + pat->frame->mat.at.y = f832; + deltaRot = icos(desireRot); + pat->frame->mat.at.z = deltaRot; + } + + xVec3Cross(&pat->frame->mat.right, &pat->frame->mat.up, &pat->frame->mat.at); + + return retval; +} + +/* + I think the multi-dimensional box array might be changed + between PS2 and gamecube. + When we use the PS2 dwarf: bossPatBox box[3][8]; 3 * 8 = 24 + 1. the compiler generates addi r3, r3, 0x78 for the loop, which is incorrect + 2. The hardcoded loop values are both 4 and 6, and 4 * 6 = 24. + I think it's supposed to be bossPatBox box[4][6] instead. + because the two issues above are resolved and things make more sense this way + and the box arrays still take up the same size. +*/ +void zNPCBPatrick::hiddenByCutscene() +{ + for (S32 i = 0; i < 2; i++) + { + this->underwear[i]->state = this->underwear[i]->state & ~0x3F | 1; + zEntEvent(this->underwear[i], 0x55); + this->underwear[i]->timer = f832; + } + + switch (this->round) + { + case 1: + { + zEntPlayer_SNDStop(ePlayerSnd_Heli); + globals.player.lassoInfo.swingTarget = NULL; + gCurrentPlayer = eCurrentPlayerSpongeBob; + + for (S32 i = 0; i < 4; i++) + { + for (S32 j = 0; j < 6; j++) + { + bossPatBox* bx = &this->box[i][j]; + bx->velocity = f832; + bx->flags = 0; + bx->pos = f1141 + bx->minY; + } + } + + this->backBox.velocity = f832; + this->backBox.flags = 0; + this->backBox.pos = f1141 + this->backBox.minY; + + break; + } + case 2: + { + gCurrentPlayer = eCurrentPlayerSandy; + zEntEvent(this->safeGroundPortal, 0x10); + xEntShow(this->fudgeHandle); + break; + } + case 3: + { + zEntPlayer_SNDStop(ePlayerSnd_Heli); + globals.player.lassoInfo.swingTarget = NULL; + gCurrentPlayer = eCurrentPlayerSpongeBob; + zEntEvent(this->safeGroundPortal, 0x10); + + for (S32 i = 0; i < 4; i++) + { + for (S32 j = 0; j < 6; j++) + { + bossPatBox* bx = &this->box[i][j]; + bx->velocity = f832; + bx->flags = 0; + bx->pos = f1141 + bx->minY; + } + } + + this->backBox.velocity = f832; + this->backBox.flags = 0; + this->backBox.pos = f1141 + this->backBox.minY; + + xEntHide(this->fudgeHandle); + + break; + } + case 4: + { + gCurrentPlayer = eCurrentPlayerSpongeBob; + zEntEvent(this->safeGroundPortal, 0x10); + break; + } + } +} + +void zNPCBPatrick_AddBoundEntsToGrid(zScene* scn) +{ + if (sOthersHaventBeenAdded) + { + sOthersHaventBeenAdded = false; + + for (S32 i = 0; i < 4; i++) + { + xEnt* ent = sPat_Ptr->boundList[i]; + + if (xGridEntIsTooBig(&colls_grid, ent)) + { + xGridAdd(&colls_oso_grid, ent); + + if (xGridEntIsTooBig(&colls_oso_grid, ent)) + { + ent->gridb.oversize = 2; + } + else + { + ent->gridb.oversize = 1; + } + } + else + { + xGridAdd(&colls_grid, ent); + ent->gridb.oversize = 0; + } + } + } + else + { + sPat_Ptr = NULL; + } +} + +S32 zNPCGoalBossPatIdle::Enter(F32 dt, void* unk) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)this->GetOwner(); + this->timeInGoal = f832; + pat->bossFlags |= 0x20; + xVec3Init(&pat->frame->vel, f832, f832, f832); + return zNPCGoalCommon::Enter(dt, unk); +} + +S32 zNPCGoalBossPatIdle::Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)this->GetOwner(); + this->timeInGoal += dt; + Pat_FaceTarget(pat, (xVec3*)&globals.player.ent.model->Mat->pos, f1673, dt); + return xGoal::Process(trantype, dt, ctxt, scene); +} + +S32 zNPCGoalBossPatRun::Enter(F32 dt, void* unk) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)this->GetOwner(); + + this->timeInGoal = f832; + + U32 hash = xStrHash("b201_rp_run_loop"); + + this->runSndID = + xSndPlay3D(hash, f1671, f832, (U32)0, (U32)0, pat, f891, f1659, SND_CAT_GAME, f832); + + pat->bossFlags |= 0x20; + + return zNPCGoalCommon::Enter(dt, unk); +} + +S32 zNPCGoalBossPatRun::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)this->GetOwner(); + + this->timeInGoal += dt; + + return xGoal::Process(trantype, dt, updCtxt, xscn); +} + +S32 zNPCGoalBossPatRun::Exit(F32 dt, void* unk) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)this->GetOwner(); + xSndStop(this->runSndID); + return xGoal::Exit(dt, unk); +} + +S32 zNPCGoalBossPatSmack::Enter(F32 dt, void* unk) +{ + zNPCBPatrick* pat = (zNPCBPatrick*)this->GetOwner(); + + this->timeInGoal = f832; + this->globNum = f832; + + pat->bossFlags |= 0x20; + pat->numMissesInARow++; + + return zNPCGoalCommon::Enter(dt, unk); +} + +S32 zNPCGoalBossPatSmack::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + /* + signed int i; // r19 + class zNPCBPatrick * pat; // r18 + signed int playSmack; // r16 + class xVec3 offset; // r29+0x110 + class xVec3 cone; // r29+0x100 + signed int numGlobs; // r17 + class xCollis colls; // r29+0xB0 + */ + xVec3 offset; + xVec3 cone; + xCollis colls; + + zNPCBPatrick* pat = (zNPCBPatrick*)this->GetOwner(); + + S32 playSmack = 0; + + if (this->timeInGoal <= f1675) + { + playSmack = 1; + } + + this->timeInGoal += dt; + + Pat_FaceTarget(pat, (xVec3*)&globals.player.ent.model->Mat->pos, f1673, dt); + + if ((this->timeInGoal > f1675) && this->timeInGoal < f831) + { + xVec3Init(&offset, f832, f832, f832); + GetBonePos(&cone, (xMat4x3*)pat->model->Mat, sBone[9], &offset); + + if (playSmack) + { + xSndPlay3D(xStrHash("b201_rp_smack"), f1671, f832, 0, 0, &cone, f1142, f1659, + SND_CAT_GAME, f832); + } + + S32 numGlobs = 0x4330; + // F32 rand = xurand(); + + // lines 114-170 (objdiff) are super confusing for me + F32 f1 = xurand(); + F32 f0 = f1046; + F32 f2 = f1056; + + f1 = f0 + f1; + + f0 = this->globNum; + f1 = f2 * f1; + f0 = dt * f1 + f0; + this->globNum = f0; + // A * C + B + + f2 = this->globNum; + f1 = f875; + + numGlobs = this->globNum; + + // this->globNum = f1056 * (f1046 * xurand()) + this->globNum; + + for (S32 i = 0; i < numGlobs; i++) + { + bossPatGlob* glob = pat->getNextFreeGlob(); + glob->t = f832; + glob->path.gravity = f832; + glob->path.maxTime = f1678 * xurand() + f831; + glob->path.gravity = f1055; + + xVec3Copy(&glob->path.initPos, &cone); + xVec3Copy(&glob->lastPos, &glob->path.initPos); + xVec3Copy(&glob->path.initPos, (xVec3*)&pat->model->Mat->at); + + xVec3AddScaled(&glob->path.initPos, (xVec3*)&pat->model->Mat->right, + f1676 * xurand() - f1046); + + glob->path.initPos.x *= f1049 * (xurand() + f891); + glob->path.initPos.y *= f1670 * (xurand() + f891); + glob->path.initPos.z *= f1049 * (xurand() + f891); + + xParabolaHitsEnv(&glob->path, globals.sceneCur->env, &colls); + + if (colls.flags & 1) + { + glob->path.maxTime = colls.dist; + xVec3Copy(&glob->norm, &cone); + glob->flags |= 2; + } + + colls.flags &= 0xfffffffe; + + pat->ParabolaHitsConveyors(&glob->path, &colls); + + if (colls.flags & 1) + { + glob->path.maxTime = colls.dist; + glob->flags |= 2; + + if (colls.tohit.x < f1679 && colls.tohit.x > f1680 && colls.tohit.z > f1681) + { + glob->flags |= 8; + xVec3Init(&glob->norm, f832, f831, f832); + glob->conv = (zPlatform*)colls.optr; + + xVec3SMul(&glob->convVel, (xVec3*)&glob->conv->bound.mat->right, + glob->conv->passet->cb.speed); + } + else + { + xVec3Init(&glob->norm, f832, f870, f832); + } + } + } + } + + return xGoal::Process(trantype, dt, updCtxt, xscn); +} + +void StartFreezeBreath() +{ + zNPCBPatrick* pat = sPat_Ptr; + + pat->parList[0] = NULL; + pat->parList[1] = NULL; + pat->parList[2] = NULL; + pat->parList[3] = NULL; + + pat->numParticles = 0; + pat->particleTimer = f832; +} + +void EmitFreezeBreath(xVec3* pos, xVec3* vel, F32 dt, F32 elapsed, F32 total) +{ + zNPCBPatrick* pat = sPat_Ptr; + + xVec3Copy(&pat->freezeBreathSetting.vel, vel); + xVec3Copy(&pat->freezeBreathSetting.pos, pos); + + F32 x = pat->freezeBreathSetting.vel.x; + F32 z = pat->freezeBreathSetting.vel.z; + F32 dVar6 = xsqrt(x * x + z * z); + pat->freezeBreathSetting.vel.y = f2596 * dVar6; + + dVar6 = xVec3Length(&pat->freezeBreathSetting.vel); + xVec3SMulBy(&pat->freezeBreathSetting.vel, f2597 / dVar6); + + pat->lastEmitted = + xParEmitterEmitCustom(pat->freezeBreathEmitter, dt, &pat->freezeBreathSetting); + + if (pat->numParticles < 4 && (elapsed / total) > pat->numParticles / f1051 && pat->lastEmitted) + { + pat->parList[pat->numParticles] = pat->lastEmitted; + pat->numParticles++; + } +} + +void StopFreezeBreath() +{ + zNPCBPatrick* pat = sPat_Ptr; + + if (!pat->lastEmitted) + { + return; + } + + pat->parList[pat->numParticles] = pat->lastEmitted; + pat->numParticles++; +} -void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) +static void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) { F32 x = m->right.x * v->x + m->up.x * v->y + m->at.x * v->z; F32 y = m->right.y * v->x + m->up.y * v->y + m->at.y * v->z; @@ -16,10 +1805,11 @@ void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) o->z = z; } -void Pat_ResetGlobalStuff() +WEAK void xDebugAddTweak(const char*, U32*, U32, U32, const tweak_callback*, void*, U32) { } -void xDebugAddTweak(const char*, U32*, U32, U32, const tweak_callback*, void*, U32) +S32 BoundEventCB(xBase*, xBase*, U32, const F32*, xBase*) { + return 1; } diff --git a/src/SB/Game/zNPCTypeBossPatrick.h b/src/SB/Game/zNPCTypeBossPatrick.h index dfb0b911..4a43351a 100644 --- a/src/SB/Game/zNPCTypeBossPatrick.h +++ b/src/SB/Game/zNPCTypeBossPatrick.h @@ -8,27 +8,34 @@ #include "zEntPickup.h" #include "xCamera.h" +#include "zNPCTypeVillager.h" -struct zNPCNewsFish; +class newsfishSound +{ + // total size: 0x8 +public: + char* soundName; // offset 0x0, size 0x4 + unsigned int soundID; // offset 0x4, size 0x4 +}; struct bossPatGlob { - xParabola path; - F32 t; - xVec3 lastPos; - xVec3 norm; - xVec3 convVel; - zPlatform* conv; - U32 flags; + xParabola path; // offset 0x0, size 0x24 + F32 t; // offset 0x24, size 0x4 + xVec3 lastPos; // offset 0x28, size 0xC + xVec3 norm; // offset 0x34, size 0xC + xVec3 convVel; // offset 0x40, size 0xC + zPlatform* conv; // offset 0x4C, size 0x4 + U32 flags; // offset 0x50, size 0x4 }; struct bossPatBox { xEnt* box; - F32 velocity; - F32 pos; - F32 minY; - U32 flags; + F32 velocity; // 0x1594 + F32 pos; // 0x1598 + F32 minY; // 0x159C + U32 flags; // 0x15A0 }; struct bossPatShard @@ -41,76 +48,101 @@ struct bossPatShard struct zNPCBPatrick : zNPCBoss { - U32 bossFlags; - S32 hitPoints; - S32 round; - F32 gooHeight; - S32 gooLevel; - S32 notSwingingLastFrame; - xEnt* gooObj; - RpAtomic* spitModel; - RpAtomic* splatModel; - xVec3 arenaExtent; - xVec3 fudgePos; - xVec3 fudgeFace; - S32 numTasks; - S32 currTask; - S32 task[20]; - bossPatGlob glob[50]; - S32 currGlob; - F32 splatTimer; - xEnt** boundList; - U32 chuckFlags[3]; - zNPCCommon* chuckList[3]; - zMovePoint* chuckMovePoint[3]; - xParEmitterCustomSettings freezeBreathSetting; - zParEmitter* freezeBreathEmitter; - xPar* parList[4]; - xPar* lastEmitted; - S32 numParticles; - F32 particleTimer; - F32 frozenTimer; - xAnimState* animState; - xAnimTransitionList* animTranList; - xEnt* fudgeHandle; - zParEmitter* fudgeEmitter; - zParEmitter* steamEmitter; - bossPatBox box[3][8]; - bossPatBox backBox; - zShrapnelAsset* boxBreak; - zShrapnelAsset* boxSplash; - F32 boxLandSndTimer; - F32 boxSplashSndTimer; - xEnt* swinger[8]; - S32 currSwinger; - F32 origSwingerHeight; - F32 swingTimer; - xModelInstance* frozenSB; - xModelInstance* frozenSBIce; - RpAtomic* shardModel; - bossPatShard shard[10]; - F32 iceScale; - F32 shakeAmp; - F32 shakePhase; - zShrapnelAsset* iceBreak; - RwRaster* iceWaveRaster; - zCutsceneMgr* round1Csn; - zCutsceneMgr* round2Csn; - zCutsceneMgr* round3Csn; - F32 csnTimer; - _zPortal* safeGroundPortal; - zNPCNewsFish* newsfish; - U32 nfFlags; - F32 badHitTimer; - S32 numPCHitsInARow; - S32 numMissesInARow; - S32 firstTimeR1Csn; - S32 firstUpdate; - zEntPickup* underwear[2]; - zPlatform* conveyorBelt[7]; + U32 bossFlags; // offset 0x2B4, size 0x4 + S32 hitPoints; // offset 0x2B8, size 0x4 + S32 round; // offset 0x2BC, size 0x4 + F32 gooHeight; // offset 0x2C0, size 0x4 + S32 gooLevel; // offset 0x2C4, size 0x4 + S32 notSwingingLastFrame; // offset 0x2C8, size 0x4 + xEnt* gooObj; // offset 0x2CC, size 0x4 + RpAtomic* spitModel; // offset 0x2D0, size 0x4 + RpAtomic* splatModel; // offset 0x2D4, size 0x4 + xVec3 arenaExtent; // offset 0x2D8, size 0xC + xVec3 fudgePos; // offset 0x2E4, size 0xC + xVec3 fudgeFace; // offset 0x2F0, size 0xC + S32 numTasks; // offset 0x2FC, size 0x4 + S32 currTask; // offset 0x300, size 0x4 + S32 task[20]; // offset 0x304, size 0x50 + bossPatGlob glob[50]; // offset 0x354, size 0x1068 + S32 currGlob; // offset 0x13BC, size 0x4 + F32 splatTimer; // offset 0x13C0, size 0x4 + xEnt** boundList; // offset 0x13C4, size 0x4 + U32 chuckFlags[3]; // offset 0x13C8, size 0xC + zNPCCommon* chuckList[3]; // offset 0x13D4, size 0xC + zMovePoint* chuckMovePoint[3]; // offset 0x13E0, size 0xC + xParEmitterCustomSettings freezeBreathSetting; // offset 0x13EC, size 0x16C + zParEmitter* freezeBreathEmitter; // offset 0x1558, size 0x4 + xPar* parList[4]; // offset 0x155C, size 0x10 + xPar* lastEmitted; // offset 0x156C, size 0x4 + S32 numParticles; // offset 0x1570, size 0x4 + F32 particleTimer; // offset 0x1574, size 0x4 + F32 frozenTimer; // offset 0x1578, size 0x4 + xAnimState* animState; // offset 0x157C, size 0x4 + xAnimTransitionList* animTranList; // offset 0x1580, size 0x4 + xEnt* fudgeHandle; // offset 0x1584, size 0x4 + zParEmitter* fudgeEmitter; // offset 0x1588, size 0x4 + zParEmitter* steamEmitter; // offset 0x158C, size 0x4 + bossPatBox box[4][6]; // offset 0x1590, size 0x1E0 + bossPatBox backBox; // offset 0x1770, size 0x14 + zShrapnelAsset* boxBreak; // offset 0x1784, size 0x4 + zShrapnelAsset* boxSplash; // offset 0x1788, size 0x4 + F32 boxLandSndTimer; // offset 0x178C, size 0x4 + F32 boxSplashSndTimer; // offset 0x1790, size 0x4 + xEnt* swinger[8]; // offset 0x1794, size 0x20 + S32 currSwinger; // offset 0x17B4, size 0x4 + F32 origSwingerHeight; // offset 0x17B8, size 0x4 + F32 swingTimer; // offset 0x17BC, size 0x4 + xModelInstance* frozenSB; // offset 0x17C0, size 0x4 + xModelInstance* frozenSBIce; // offset 0x17C4, size 0x4 + RpAtomic* shardModel; // offset 0x17C8, size 0x4 + bossPatShard shard[10]; // offset 0x17CC, size 0xF0 + F32 iceScale; // offset 0x18BC, size 0x4 + F32 shakeAmp; // offset 0x18C0, size 0x4 + F32 shakePhase; // offset 0x18C4, size 0x4 + zShrapnelAsset* iceBreak; // offset 0x18C8, size 0x4 + RwRaster* iceWaveRaster; // offset 0x18CC, size 0x4 + zCutsceneMgr* round1Csn; // offset 0x18D0, size 0x4 + zCutsceneMgr* round2Csn; // offset 0x18D4, size 0x4 + zCutsceneMgr* round3Csn; // offset 0x18D8, size 0x4 + F32 csnTimer; // offset 0x18DC, size 0x4 + _zPortal* safeGroundPortal; // offset 0x18E0, size 0x4 + zNPCNewsFish* newsfish; // offset 0x18E4, size 0x4 + U32 nfFlags; // offset 0x18E8, size 0x4 + F32 badHitTimer; // offset 0x18EC, size 0x4 + S32 numPCHitsInARow; // offset 0x18F0, size 0x4 + S32 numMissesInARow; // offset 0x18F4, size 0x4 + S32 firstTimeR1Csn; // offset 0x18F8, size 0x4 + S32 firstUpdate; // offset 0x18FC, size 0x4 + zEntPickup* underwear[2]; // offset 0x1900, size 0x8 + zPlatform* conveyorBelt[7]; // offset 0x1908, size 0x1C xBinaryCamera bossCam; zNPCBPatrick(S32 myType); + + void Init(xEntAsset* asset); + void Setup(); + void SelfSetup(); + void Reset(); + void Destroy(); + U32 AnimPick(S32 rawgoal, en_NPC_GOAL_SPOT gspot, xGoal* goal); + void Process(xScene* xscn, F32 dt); + void DuploNotice(en_SM_NOTICES note, void* data); + void Damage(en_NPC_DAMAGE_TYPE dmg_type, xBase* who, const xVec3* vec_hit); + + void RenderGlobs(); + void RenderFrozenPlayer(); + void RenderExtra(); + void NewTime(xScene* xscn, F32 dt); + S32 nextGoal(); + bossPatGlob* getNextFreeGlob(); // Not in PS2 DWARF + void playSplat(xVec3* pos); + U32 canSpawnChucks(); + void gotoRound(S32 num); + F32 ConveyorTimeLeft(zPlatform* platform, xVec3* vec_unk); // Not in PS2 DWARF + void ParabolaHitsConveyors(xParabola* parabola, xCollis* collis_unk); + void bossPatBoxCheckCollide(bossPatBox* bx); // Not in PS2 DWARF + void bossPatBoxUpdate(bossPatBox* bx, F32 dt); + void hiddenByCutscene(); }; struct zNPCGoalBossPatIdle : zNPCGoalCommon @@ -121,6 +153,9 @@ struct zNPCGoalBossPatIdle : zNPCGoalCommon zNPCGoalBossPatIdle(S32 goalID) : zNPCGoalCommon(goalID) { } + + S32 Enter(F32 dt, void* unk); + S32 Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene); }; struct zNPCGoalBossPatTaunt : zNPCGoalCommon @@ -163,17 +198,24 @@ struct zNPCGoalBossPatRun : zNPCGoalCommon zNPCGoalBossPatRun(S32 goalID) : zNPCGoalCommon(goalID) { } + + S32 Enter(F32 dt, void* unk); + S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn); + S32 Exit(F32 dt, void* unk); }; struct zNPCGoalBossPatSmack : zNPCGoalCommon { - F32 timeInGoal; - U32 stage; - F32 globNum; + F32 timeInGoal; // 0x4c + U32 stage; // 0x50 + F32 globNum; // 0x54 zNPCGoalBossPatSmack(S32 goalID) : zNPCGoalCommon(goalID) { } + + S32 Enter(F32 dt, void* unk); + S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn); }; struct zNPCGoalBossPatFreeze : zNPCGoalCommon @@ -215,11 +257,11 @@ struct zNPCGoalBossPatSpin : zNPCGoalCommon struct zNPCGoalBossPatFudge : zNPCGoalCommon { - F32 timeInGoal; - U32 stage; - F32 lerp; - F32 globNum; - U32 vomitSndID; + F32 timeInGoal; // offset 0x4C, size 0x4 + U32 stage; // offset 0x50, size 0x4 + F32 lerp; // offset 0x54, size 0x4 + F32 globNum; // offset 0x58, size 0x4 + U32 vomitSndID; // offset 0x5C, size 0x4 zNPCGoalBossPatFudge(S32 goalID) : zNPCGoalCommon(goalID) { diff --git a/src/SB/Game/zNPCTypeBossPlankton.cpp b/src/SB/Game/zNPCTypeBossPlankton.cpp index 75295abb..1f67bbe9 100644 --- a/src/SB/Game/zNPCTypeBossPlankton.cpp +++ b/src/SB/Game/zNPCTypeBossPlankton.cpp @@ -14,3 +14,43 @@ S32 zNPCBPlankton::IsAlive() { return 1; } + +U8 zNPCBPlankton::ColPenFlags() const +{ + return 0; +} + +U8 zNPCBPlankton::ColChkFlags() const +{ + return 0; +} + +U8 zNPCBPlankton::ColChkByFlags() const +{ + return 16; +} + +S32 zNPCGoalBPlanktonBomb::Process(en_trantype*, F32, void*, xScene*) +{ + return 0; +} + +S32 zNPCGoalBPlanktonMissle::Process(en_trantype*, F32, void*, xScene*) +{ + return 0; +} + +S32 zNPCGoalBPlanktonWall::Process(en_trantype*, F32, void*, xScene*) +{ + return 0; +} + +S32 zNPCGoalBPlanktonMove::Process(en_trantype*, F32, void*, xScene*) +{ + return 0; +} + +S32 zNPCGoalBPlanktonTaunt::Process(en_trantype*, F32, void*, xScene*) +{ + return 0; +} diff --git a/src/SB/Game/zNPCTypeBossPlankton.h b/src/SB/Game/zNPCTypeBossPlankton.h index 075f3dbf..6efefe25 100644 --- a/src/SB/Game/zNPCTypeBossPlankton.h +++ b/src/SB/Game/zNPCTypeBossPlankton.h @@ -109,6 +109,9 @@ struct zNPCBPlankton : zNPCBoss void render_debug(); void update_animation(float); S32 IsAlive(); + U8 ColPenFlags() const; + U8 ColChkFlags() const; + U8 ColChkByFlags() const; }; struct zNPCGoalBPlanktonIdle : zNPCGoalCommon @@ -161,6 +164,7 @@ struct zNPCGoalBPlanktonTaunt : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Process(en_trantype*, float, void*, xScene*); }; struct zNPCGoalBPlanktonMove : zNPCGoalCommon @@ -168,6 +172,7 @@ struct zNPCGoalBPlanktonMove : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Process(en_trantype*, float, void*, xScene*); }; struct zNPCGoalBPlanktonStun : zNPCGoalCommon @@ -213,6 +218,7 @@ struct zNPCGoalBPlanktonWall : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Process(en_trantype*, float, void*, xScene*); }; struct zNPCGoalBPlanktonMissle : zNPCGoalCommon @@ -220,6 +226,7 @@ struct zNPCGoalBPlanktonMissle : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Process(en_trantype*, float, void*, xScene*); }; struct zNPCGoalBPlanktonBomb : zNPCGoalCommon @@ -227,6 +234,7 @@ struct zNPCGoalBPlanktonBomb : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Process(en_trantype*, float, void*, xScene*); }; #endif diff --git a/src/SB/Game/zNPCTypeBossSB1.cpp b/src/SB/Game/zNPCTypeBossSB1.cpp index 18133c2e..e7b50bdc 100644 --- a/src/SB/Game/zNPCTypeBossSB1.cpp +++ b/src/SB/Game/zNPCTypeBossSB1.cpp @@ -14,39 +14,7 @@ #include "zThrown.h" #include "zGlobals.h" -#define f822 1.0f -#define f823 0.0f -#define f824 0.2f -#define f825 3.3333333f -#define f890 100.0f -#define f891 -3.5f -#define f892 -2.0f -#define f893 3.5f -#define f894 10.0f -#define f895 2.0f -#define f896 0.6f -#define f983 5.0f -#define f984 1.3f -#define f1008 100000000000000000000000000000000000000.0f // original ASM object -#define f1019 64.0f -#define f1034 0.75f -#define f1043 1.1f -#define f1053 1.5f -#define f1054 90.25f -#define f1065 4.7666664f -#define f1088 6.2831855f -#define f1089 3.1415927f -#define f1090 -3.1415927f -#define f1091 1.5707964f -#define f1160 0.25f -#define f1161 0.5f -#define f1209 0.76666665f -#define f1223 0.05f - -static U32 sSB1_deflated[2]; - -static xVec3 BossArmTags[8] = { - // +static xVec3 BossArmTags[8] = { // { 11.507f, 4.523f, 2.53f }, { 11.635f, @@ -109,60 +77,82 @@ static xVec3 BossFeetTags[4] = { }, }; -zEnt* sSB1_armTgtHit; -zNPCB_SB1* sSB1_Ptr; // size: 0x4, address: 0x510188 +static zNPCB_SB1* sSB1_Ptr; +static zEnt* sSB1_armTgtHit; +static U32 sSB1_deflated[2]; -void test(S32 a) -{ -} +// Boss animation string table indices +#define Unknown 0 +#define Idle01 1 +#define Idle02 2 +#define Taunt01 3 +#define SmashStart 41 +#define SmashLoop 42 +#define SmashEnd 43 +#define AttackStomp 44 +#define AttackRumble 45 +#define SmashHitLeft 46 +#define SmashHitRight 47 xAnimTable* ZNPC_AnimTable_BossSB1() { + // clang-format off int ourAnims[11] = { - 1, 2, 3, 41, 42, 43, 44, 45, 46, 47, 0, + Idle01, + Idle02, + Taunt01, + SmashStart, + SmashLoop, + SmashEnd, + AttackStomp, + AttackRumble, + SmashHitLeft, + SmashHitRight, + Unknown, }; + // clang-format on xAnimTable* table = xAnimTableNew("zNPCB_SB1_Muscle", NULL, 0); - xAnimTableNewState(table, g_strz_bossanim[1], 0x10, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, - xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[2], 0, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[Idle01], 0x10, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[3], 0, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[Idle02], 0, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[41], 0x20, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[Taunt01], 0, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[42], 0x10, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[SmashStart], 0x20, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[43], 0x20, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[SmashLoop], 0x10, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[44], 0x10, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[SmashEnd], 0x20, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[45], 0x10, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[AttackStomp], 0x10, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[46], 0, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[AttackRumble], 0x10, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, + 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); + xAnimTableNewState(table, g_strz_bossanim[SmashHitLeft], 0, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - xAnimTableNewState(table, g_strz_bossanim[47], 0, 0, f822, 0x0, 0x0, f823, 0x0, 0x0, + xAnimTableNewState(table, g_strz_bossanim[SmashHitRight], 0, 0, 1.0f, 0x0, 0x0, 0.0f, 0x0, 0x0, xAnimDefaultBeforeEnter, 0x0, 0x0); - NPCC_BuildStandardAnimTran(table, g_strz_bossanim, ourAnims, 1, f824); + NPCC_BuildStandardAnimTran(table, g_strz_bossanim, ourAnims, 1, 0.2f); - xAnimTableNewTransition(table, g_strz_bossanim[41], g_strz_bossanim[42], 0x0, 0x0, 0x10, 0, - f823, f823, 0, 0, f823, 0x0); - xAnimTableNewTransition(table, g_strz_bossanim[43], g_strz_bossanim[1], 0x0, 0x0, 0x10, 0, f823, - f823, 0, 0, f823, 0x0); + xAnimTableNewTransition(table, g_strz_bossanim[SmashStart], g_strz_bossanim[SmashLoop], 0x0, + 0x0, 0x10, 0, 0.0f, 0.0f, 0, 0, 0.0f, 0x0); + xAnimTableNewTransition(table, g_strz_bossanim[SmashEnd], g_strz_bossanim[Idle01], 0x0, 0x0, + 0x10, 0, 0.0f, 0.0f, 0, 0, 0.0f, 0x0); xAnimTransition* t = table->TransitionList; while (t) { - t->BlendRecip = f825; + t->BlendRecip = 3.3333333f; t = t->Next; } return table; } -void SB1Dummy_UpdateFunc(xEnt* ent, xScene* param_2, F32 param_3) +static void SB1Dummy_UpdateFunc(xEnt* ent, xScene* param_2, F32 param_3) { if (ent->frame != NULL) { @@ -174,18 +164,19 @@ void SB1Dummy_UpdateFunc(xEnt* ent, xScene* param_2, F32 param_3) } } -void SB1Dummy_BoundFunc(xEnt* ent, xVec3* param_2) +static void SB1Dummy_BoundFunc(xEnt* ent, xVec3* param_2) { xBoundUpdate(&ent->bound); zGridUpdateEnt(ent); } -void SB1Dummy_RenderFunc(xEnt* ent) +static void SB1Dummy_RenderFunc(xEnt* ent) { xDrawSphere(&(ent->bound).sph, 0xc0006); } -S32 SB1Dummy_TgtEventFunc(xBase* to, xBase* from, U32 toEvent, const F32* param_f, xBase* param_x) +static S32 SB1Dummy_TgtEventFunc(xBase* to, xBase* from, U32 toEvent, const F32* param_f, + xBase* param_x) { if (toEvent == 360) { @@ -194,48 +185,110 @@ S32 SB1Dummy_TgtEventFunc(xBase* to, xBase* from, U32 toEvent, const F32* param_ return 1; } -void SB1_ResetGlobalStuff() +// 86% match, just some sda2 scheduling issues +static void SB1_ResetGlobalStuff() { + sSB1_Ptr->m_subModels[2]->Flags |= 1; + sSB1_Ptr->m_subModels[3]->Flags |= 1; + sSB1_Ptr->m_subModels[4]->Flags &= ~1; + sSB1_Ptr->m_subModels[5]->Flags &= ~1; + + sSB1_Ptr->m_tauntTimer = 0.0f; + + sSB1_deflated[0] = false; + sSB1_deflated[1] = false; + sSB1_armTgtHit = NULL; + + memset(sSB1_Ptr->m_stompRing, 0, sizeof(sSB1_Ptr->m_stompRing)); + + S32 i; + + for (i = 0; i < 2; i++) + { + if (sSB1_Ptr->m_armColl[i]) + { + sSB1_Ptr->m_armColl[i]->model->Flags = 0x2800; + sSB1_Ptr->m_armColl[i]->model->Next = NULL; + sSB1_Ptr->m_armColl[i]->bound.type = 1; + sSB1_Ptr->m_armColl[i]->bound.box.center = g_O3; + + sSB1_Ptr->m_armColl[i]->bound.box.box.upper.x = 100.0f; + sSB1_Ptr->m_armColl[i]->update = SB1Dummy_UpdateFunc; + sSB1_Ptr->m_armColl[i]->bupdate = SB1Dummy_BoundFunc; + sSB1_Ptr->m_armColl[i]->penby = XENT_COLLTYPE_PLYR; + sSB1_Ptr->m_armColl[i]->chkby = XENT_COLLTYPE_PLYR; + } + } + + sSB1_Ptr->m_armColl[0]->model->Data = sSB1_Ptr->m_subModels[2]->Data; + sSB1_Ptr->m_armColl[0]->model->Mat = sSB1_Ptr->m_subModels[2]->Mat; + + sSB1_Ptr->m_armColl[1]->model->Data = sSB1_Ptr->m_subModels[3]->Data; + sSB1_Ptr->m_armColl[1]->model->Mat = sSB1_Ptr->m_subModels[3]->Mat; + + if (sSB1_Ptr->m_bodyColl) + { + sSB1_Ptr->m_bodyColl->model->Flags = 0x2000; + + sSB1_Ptr->m_bodyColl->bound.type = 4; + + sSB1_Ptr->m_bodyColl->bound.box.box.lower.x = -3.5f; + sSB1_Ptr->m_bodyColl->bound.box.box.lower.y = 0.0f; + sSB1_Ptr->m_bodyColl->bound.box.box.lower.z = -2.0f; + + sSB1_Ptr->m_bodyColl->bound.box.box.upper.x = 3.5f; + sSB1_Ptr->m_bodyColl->bound.box.box.upper.y = 10.0f; + sSB1_Ptr->m_bodyColl->bound.box.box.upper.z = 2.0f; + + sSB1_Ptr->m_bodyColl->bound.mat = (xMat4x3*)sSB1_Ptr->model->Mat; + + sSB1_Ptr->m_bodyColl->update = SB1Dummy_UpdateFunc; + sSB1_Ptr->m_bodyColl->bupdate = SB1Dummy_BoundFunc; + + sSB1_Ptr->m_bodyColl->penby = XENT_COLLTYPE_PLYR; + sSB1_Ptr->m_bodyColl->chkby = XENT_COLLTYPE_PLYR; + } + + for (i = 0; i < 2; i++) + { + sSB1_Ptr->m_armTgt[i]->render = SB1Dummy_RenderFunc; + sSB1_Ptr->m_armTgt[i]->bupdate = SB1Dummy_BoundFunc; + sSB1_Ptr->m_armTgt[i]->eventFunc = SB1Dummy_TgtEventFunc; + sSB1_Ptr->m_armTgt[i]->bound.type = 1; + sSB1_Ptr->m_armTgt[i]->bound.box.center = *(xVec3*)&sSB1_Ptr->m_armTgt[i]->model->Mat->pos; + sSB1_Ptr->m_armTgt[i]->bound.box.box.upper.x = 0.6f; + } } -// Close, but no cigar void zNPCB_SB1::Init(xEntAsset* asset) { - /* - signed int i; // r19 - class xModelInstance * minst; // r5 - */ - this->zNPCCommon::Init(asset); sSB1_Ptr = this; - // xModelInstance* minst = this->model; S32 i = 0; xModelInstance* minst = this->model; while (minst) { - minst->Data->boundingSphere.radius = f890; + minst->Data->boundingSphere.radius = 100.0f; this->m_subModels[i] = minst; i = i + 1; minst = minst->Next; } - // I'm pretty sure this idea is right, but for some reason it's loading - // BossArmTags into/out of the stack??? for (i = 0; i < 4; i++) { - iModelTagSetup(this->m_leftArmTags[i], this->m_subModels[i]->Data, BossArmTags[i].x, + iModelTagSetup(&this->m_leftArmTags[i], this->m_subModels[2]->Data, BossArmTags[i].x, BossArmTags[i].y, BossArmTags[i].z); - iModelTagSetup(this->m_rightArmTags[i], this->m_subModels[i]->Data, BossArmTags[i + 4].x, + iModelTagSetup(&this->m_rightArmTags[i], this->m_subModels[3]->Data, BossArmTags[i + 4].x, BossArmTags[i + 4].y, BossArmTags[i + 4].z); } for (i = 0; i < 4; i++) { - iModelTagSetup(this->m_feetTags[i], this->m_subModels[i]->Data, BossFeetTags[i].x, + iModelTagSetup(&this->m_feetTags[i], this->m_subModels[1]->Data, BossFeetTags[i].x, BossFeetTags[i].y, BossFeetTags[i].z); } @@ -244,16 +297,16 @@ void zNPCB_SB1::Init(xEntAsset* asset) this->m_armColl[1] = (zEnt*)zSceneFindObject(xStrHash("DUMMY_ARMCOLL_RIGHT")); this->m_bodyColl = (zEnt*)zSceneFindObject(xStrHash("DUMMY_BODYCOLL")); this->m_armTgt[0] = (zEnt*)zSceneFindObject(xStrHash("DUMMY_ARMTGT_LEFT")); - this->m_armTgt[0] = (zEnt*)zSceneFindObject(xStrHash("DUMMY_ARMTGT_RIGHT")); + this->m_armTgt[1] = (zEnt*)zSceneFindObject(xStrHash("DUMMY_ARMTGT_RIGHT")); SB1_ResetGlobalStuff(); } -S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*); -S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); -S32 stompCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); -S32 smashCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); -S32 deflateCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 stompCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 smashCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 deflateCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); void zNPCB_SB1::SelfSetup() { @@ -291,7 +344,7 @@ void zNPCB_SB1::Reset() SB1_ResetGlobalStuff(); this->zNPCCommon::Reset(); this->attacking = 1; - this->attack_delay = f823; + this->attack_delay = 0.0f; if (this->psy_instinct) { @@ -308,46 +361,46 @@ U32 zNPCB_SB1::AnimPick(S32 gid, en_NPC_GOAL_SPOT gspot, xGoal* goal) { case NPC_GOAL_BOSSSB1IDLE: { - if (this->model->Anim->Single->State->ID == g_hash_bossanim[42]) + if (this->model->Anim->Single->State->ID == g_hash_bossanim[SmashLoop]) { - index = 43; + index = SmashEnd; } else { - index = 1; + index = Idle01; } break; } case NPC_GOAL_BOSSSB1TAUNT: { - index = 3; + index = Taunt01; break; } case NPC_GOAL_BOSSSB1STOMP: { - index = 44; + index = AttackStomp; break; } case NPC_GOAL_BOSSSB1SMASH: { - index = 41; + index = SmashStart; break; } case NPC_GOAL_BOSSSB1DEFLATE: { if (sSB1_armTgtHit == this->m_armTgt[0]) { - index = 46; + index = SmashHitLeft; } else { - index = 47; + index = SmashHitRight; } break; } default: { - index = 1; + index = Idle01; } } @@ -363,11 +416,11 @@ void zNPCB_SB1::Process(xScene* xscn, F32 dt) { this->attack_delay += dt; - if (this->attack_delay > f983) + if (this->attack_delay > 5.0f) { this->attacking = !this->attacking; - this->attack_delay = f823; + this->attack_delay = 0.0f; } if (this->attacking && this->psy_instinct) @@ -375,20 +428,20 @@ void zNPCB_SB1::Process(xScene* xscn, F32 dt) this->psy_instinct->Timestep(dt, NULL); } - xFXRing* ring; // needs to be declared outside to match + xFXRing* ring; for (U32 i = 0; i < 16; i++) { ring = this->m_stompRing[i]; - if (ring && ring->time > f984) + if (ring && ring->time > 1.3f) { - F32 rescale = ring->time / (ring->time + f983 * dt); + F32 rescale = ring->time / (ring->time + 5.0f * dt); ring->ring_radius_delta *= rescale; ring->ring_tilt_delta *= rescale; ring->ring_height_delta *= rescale; - ring->time += f983 * dt; + ring->time += 5.0f * dt; } } @@ -418,25 +471,25 @@ F32 zNPCB_SB1::AttackTimeLeft() { if (this->attacking == 0) { - return f823; + return 0.0f; } - return f983 - this->attack_delay; + return 5.0f - this->attack_delay; } void zNPCB_SB1::HoldUpDude() { this->attacking = 0; - this->attack_delay = f1008; + this->attack_delay = 100000000000000000000000000000000000000.0f; // heavy iron moment } void zNPCB_SB1::ThanksImDone() { this->attacking = 1; - this->attack_delay = f983; + this->attack_delay = 5.0f; } -S32 SB1_CheckFeetStomp(zNPCB_SB1* sb1, S32* goal, en_trantype* trantype) +static S32 SB1_CheckFeetStomp(zNPCB_SB1* sb1, S32* goal, en_trantype* trantype) { xVec3* player_pos = (xVec3*)&globals.player.ent.model->Mat->pos; xVec3* boss_pos = (xVec3*)&sb1->model->Mat->pos; @@ -444,7 +497,7 @@ S32 SB1_CheckFeetStomp(zNPCB_SB1* sb1, S32* goal, en_trantype* trantype) S32 result = 0; - if (dist < f1019) + if (dist < 64.0f) { result = 1; *goal = NPC_GOAL_BOSSSB1STOMP; @@ -458,7 +511,7 @@ S32 SB1_CheckFeetStomp(zNPCB_SB1* sb1, S32* goal, en_trantype* trantype) return result; } -S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) +static S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) { zNPCB_SB1* sb1 = (zNPCB_SB1*)rawgoal->GetOwner(); zNPCGoalBossSB1Idle* idle = (zNPCGoalBossSB1Idle*)rawgoal; @@ -470,9 +523,9 @@ S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) return nextgoal; } - if (idle->timeInGoal > f1034) + if (idle->timeInGoal > 0.75f) { - if (sb1->m_tauntTimer < f823) + if (sb1->m_tauntTimer < 0.0f) { nextgoal = NPC_GOAL_BOSSSB1TAUNT; *trantype = GOAL_TRAN_SET; @@ -487,7 +540,7 @@ S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) return nextgoal; } -S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCB_SB1* sb1 = (zNPCB_SB1*)rawgoal->GetOwner(); @@ -498,7 +551,7 @@ S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } - if (sb1->AnimTimeRemain(NULL) < f1043 * dt) + if (sb1->AnimTimeRemain(NULL) < 1.1f * dt) { nextgoal = NPC_GOAL_BOSSSB1IDLE; *trantype = GOAL_TRAN_SET; @@ -507,21 +560,21 @@ S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } -S32 stompCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 stompCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCGoalBossSB1Stomp* stomp = (zNPCGoalBossSB1Stomp*)rawgoal; zNPCB_SB1* sb1 = (zNPCB_SB1*)rawgoal->GetOwner(); S32 nextgoal = 0; - if (stomp->timeInGoal > f1053) + if (stomp->timeInGoal > 1.5f) { xVec3* player_pos = (xVec3*)&globals.player.ent.model->Mat->pos; xVec3* boss_pos = (xVec3*)&sb1->model->Mat->pos; F32 dist = xVec3Dist2(boss_pos, player_pos); - if (dist > f1054) + if (dist > 90.25f) { - if (sb1->AnimTimeRemain(NULL) < f1043 * dt) + if (sb1->AnimTimeRemain(NULL) < 1.1f * dt) { nextgoal = NPC_GOAL_BOSSSB1IDLE; *trantype = GOAL_TRAN_SET; @@ -533,7 +586,7 @@ S32 stompCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) } // 91% match, just has a register scheduling issue -S32 smashCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 smashCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCGoalBossSB1Smash* smash = (zNPCGoalBossSB1Smash*)rawgoal; zNPCB_SB1* sb1 = (zNPCB_SB1*)rawgoal->GetOwner(); @@ -552,7 +605,7 @@ S32 smashCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } - if (smash->timeInGoal > f1065) + if (smash->timeInGoal > 4.7666664f) { nextgoal = NPC_GOAL_BOSSSB1IDLE; *trantype = GOAL_TRAN_SET; @@ -561,13 +614,13 @@ S32 smashCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } -S32 deflateCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 deflateCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCB_SB1* sb1 = (zNPCB_SB1*)rawgoal->GetOwner(); S32 nextgoal = 0; - if (sb1->AnimTimeRemain(NULL) < f1043 * dt) + if (sb1->AnimTimeRemain(NULL) < 1.1f * dt) { nextgoal = NPC_GOAL_BOSSSB1IDLE; *trantype = GOAL_TRAN_SET; @@ -576,14 +629,14 @@ S32 deflateCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } -S32 SB1_FaceTarget(zNPCB_SB1* sb1, xVec3* target, F32 dt) +static S32 SB1_FaceTarget(zNPCB_SB1* sb1, xVec3* target, F32 dt) { S32 retval = 0; xVec3 newAt; xVec3Sub(&newAt, target, (xVec3*)&sb1->model->Mat->pos); - newAt.y = f823; + newAt.y = 0.0f; F32 a = xVec3Normalize(&newAt, &newAt); F32 currRot = xatan2(sb1->model->Mat->at.x, sb1->model->Mat->at.z); @@ -591,17 +644,17 @@ S32 SB1_FaceTarget(zNPCB_SB1* sb1, xVec3* target, F32 dt) F32 diffRot = desireRot - currRot; - if (diffRot > f1089) + if (diffRot > 3.1415927f) { - diffRot -= f1088; + diffRot -= 6.2831855f; } - if (diffRot < f1090) + if (diffRot < -3.1415927f) { - diffRot += f1088; + diffRot += 6.2831855f; } - F32 deltaRot = f1091 * dt; + F32 deltaRot = 1.5707964f * dt; if ((F32)iabs(diffRot) < deltaRot) { @@ -610,7 +663,7 @@ S32 SB1_FaceTarget(zNPCB_SB1* sb1, xVec3* target, F32 dt) } else { - if (diffRot < f823) + if (diffRot < 0.0f) { deltaRot = -deltaRot; } @@ -618,7 +671,7 @@ S32 SB1_FaceTarget(zNPCB_SB1* sb1, xVec3* target, F32 dt) desireRot = currRot + deltaRot; deltaRot = isin(currRot + deltaRot); sb1->frame->mat.at.x = deltaRot; - sb1->frame->mat.at.y = f823; + sb1->frame->mat.at.y = 0.0f; deltaRot = icos(desireRot); sb1->frame->mat.at.z = deltaRot; } @@ -631,16 +684,16 @@ S32 SB1_FaceTarget(zNPCB_SB1* sb1, xVec3* target, F32 dt) S32 zNPCGoalBossSB1Idle::Enter(F32 dt, void* updCtxt) { zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); - this->timeInGoal = f823; - xVec3Init(&sb1->frame->vel, f823, f823, f823); + this->timeInGoal = 0.0f; + xVec3Init(&sb1->frame->vel, 0.0f, 0.0f, 0.0f); return this->zNPCGoalCommon::Enter(dt, updCtxt); } -S32 zNPCGoalBossSB1Idle::Process(en_trantype* trantype, float dt, void* ctxt, xScene* scene) +S32 zNPCGoalBossSB1Idle::Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene) { zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); - if (sb1->model->Anim->Single->State->ID == g_hash_bossanim[1]) + if (sb1->model->Anim->Single->State->ID == g_hash_bossanim[Idle01]) { this->timeInGoal += dt; sb1->m_tauntTimer -= dt; @@ -654,12 +707,12 @@ S32 zNPCGoalBossSB1Idle::Process(en_trantype* trantype, float dt, void* ctxt, xS S32 zNPCGoalBossSB1Taunt::Enter(F32 dt, void* updCtxt) { zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); - this->timeInGoal = f823; - sb1->m_tauntTimer = f983; + this->timeInGoal = 0.0f; + sb1->m_tauntTimer = 5.0f; return this->zNPCGoalCommon::Enter(dt, updCtxt); } -S32 zNPCGoalBossSB1Taunt::Process(en_trantype* trantype, float dt, void* ctxt, xScene* scene) +S32 zNPCGoalBossSB1Taunt::Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene) { zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); @@ -673,70 +726,11 @@ S32 zNPCGoalBossSB1Taunt::Process(en_trantype* trantype, float dt, void* ctxt, x S32 zNPCGoalBossSB1Stomp::Enter(F32 dt, void* updCtxt) { zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); - this->timeInGoal = f823; + this->timeInGoal = 0.0f; return this->zNPCGoalCommon::Enter(dt, updCtxt); } -// scheduling memes preventing match -S32 zNPCGoalBossSB1Smash::Enter(F32 dt, void* updCtxt) -{ - zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); - sSB1_armTgtHit = NULL; - this->timeInGoal = f823; - return this->zNPCGoalCommon::Enter(dt, updCtxt); -} - -S32 zNPCGoalBossSB1Smash::Exit(F32 dt, void* updCtxt) -{ - zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); - - sb1->m_armTgt[0]->model->Mat->pos.y = f890; - sb1->m_armTgt[1]->model->Mat->pos.y = f890; - - sSB1_Ptr->m_armTgt[0]->bound.box.center = (xVec3&)sSB1_Ptr->m_armTgt[0]->model->Mat->pos; - sSB1_Ptr->m_armTgt[1]->bound.box.center = (xVec3&)sSB1_Ptr->m_armTgt[1]->model->Mat->pos; - - SB1Dummy_BoundFunc(sb1->m_armTgt[0], NULL); - SB1Dummy_BoundFunc(sb1->m_armTgt[1], NULL); - - return this->zNPCGoalCommon::Exit(dt, updCtxt); -} - -// WIP, only 32% matching -S32 zNPCGoalBossSB1Deflate::Enter(F32 dt, void* updCtxt) -{ - zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); - this->timeInGoal = f823; - - RpGeometry* srcGeom; // r18 - RpGeometry* dstGeom; // r17 - xAnimState* deflateState; // r16 - - // WIP - // I think might be a loop the compiler unrolled, not sure though - for (S32 i = 0; i < 2; i++) - { - if (sSB1_armTgtHit == sb1->m_armTgt[i]) - { - srcGeom = sb1->m_subModels[i]->Data->geometry; - dstGeom = sb1->m_subModels[i + 1]->Data->geometry; - deflateState = xAnimTableGetStateID(sb1->model->Anim->Table, g_hash_bossanim[i]); - } - } - - this->morphVertCount = srcGeom->numVertices; - this->modelVec = srcGeom->morphTarget->verts; - this->modelGeom = srcGeom; - this->targetVec = srcGeom->morphTarget->verts; - - memcpy(this->morphVertBuf, this->modelVec, this->morphVertCount * sizeof(RwV3d)); - - this->morphInvTime = f822 / (deflateState->Data->Duration - f1223); - - return this->zNPCGoalCommon::Enter(dt, updCtxt); -} - -void AddStompRing(zNPCB_SB1* sb1, xVec3* pos) +static void AddStompRing(zNPCB_SB1* sb1, xVec3* pos) { for (S32 i = 0; i < 16; i++) { @@ -758,7 +752,7 @@ void AddStompRing(zNPCB_SB1* sb1, xVec3* pos) } } -S32 zNPCGoalBossSB1Stomp::Process(en_trantype* trantype, float dt, void* ctxt, xScene* scene) +S32 zNPCGoalBossSB1Stomp::Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene) { zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); @@ -769,7 +763,7 @@ S32 zNPCGoalBossSB1Stomp::Process(en_trantype* trantype, float dt, void* ctxt, x SB1_FaceTarget(sb1, (xVec3*)&globals.player.ent.model->Mat->pos, dt); - if (this->timeInGoal > f1160) + if (this->timeInGoal > 0.25f) { if (sb1->model->Anim->Single->LastTime > sb1->model->Anim->Single->Time) { @@ -779,11 +773,11 @@ S32 zNPCGoalBossSB1Stomp::Process(en_trantype* trantype, float dt, void* ctxt, x sb1->m_subModels[1]->Mat, &feetTag[i]); } - xVec3Lerp(&wavePt[0], &feetTag[0], &feetTag[1], f1161); - xVec3Lerp(&wavePt[1], &feetTag[2], &feetTag[3], f1161); + xVec3Lerp(&wavePt[0], &feetTag[0], &feetTag[1], 0.5f); + xVec3Lerp(&wavePt[1], &feetTag[2], &feetTag[3], 0.5f); - wavePt[0].y = f1160; - wavePt[1].y = f1160; + wavePt[0].y = 0.25f; + wavePt[1].y = 0.25f; AddStompRing(sb1, &wavePt[0]); AddStompRing(sb1, &wavePt[1]); @@ -793,6 +787,116 @@ S32 zNPCGoalBossSB1Stomp::Process(en_trantype* trantype, float dt, void* ctxt, x return xGoal::Process(trantype, dt, ctxt, scene); } +// scheduling memes preventing perfect match +S32 zNPCGoalBossSB1Smash::Enter(F32 dt, void* updCtxt) +{ + zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); + sSB1_armTgtHit = NULL; + this->timeInGoal = 0.0f; + return this->zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBossSB1Smash::Exit(F32 dt, void* updCtxt) +{ + zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); + + sb1->m_armTgt[0]->model->Mat->pos.y = 100.0f; + sb1->m_armTgt[1]->model->Mat->pos.y = 100.0f; + + sSB1_Ptr->m_armTgt[0]->bound.box.center = (xVec3&)sSB1_Ptr->m_armTgt[0]->model->Mat->pos; + sSB1_Ptr->m_armTgt[1]->bound.box.center = (xVec3&)sSB1_Ptr->m_armTgt[1]->model->Mat->pos; + + SB1Dummy_BoundFunc(sb1->m_armTgt[0], NULL); + SB1Dummy_BoundFunc(sb1->m_armTgt[1], NULL); + + return this->zNPCGoalCommon::Exit(dt, updCtxt); +} + +S32 zNPCGoalBossSB1Smash::Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene) +{ + xVec3 curTag; + + zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); + + this->timeInGoal += dt; + + if (sb1->model->Anim->Single->State->ID == g_hash_bossanim[SmashLoop] || + (sb1->model->Anim->Single->Time > 0.76666665f)) + { + if (!sSB1_deflated[0]) + { + xVec3 sumTag = { 0, 0, 0 }; + + for (S32 i = 0; i < 4; i++) + { + iModelTagEval(sb1->m_subModels[2]->Data, &sb1->m_leftArmTags[i], + sb1->m_subModels[2]->Mat, &curTag); + xVec3Add(&sumTag, &sumTag, &curTag); + } + + xVec3SMulBy(&sumTag, 0.25f); + xVec3* pos = (xVec3*)&sSB1_Ptr->m_armTgt[0]->model->Mat->pos; + *pos = sumTag; + sSB1_Ptr->m_armTgt[0]->bound.sph.center = sumTag; + SB1Dummy_BoundFunc(sb1->m_armTgt[0], NULL); + } + if (!sSB1_deflated[1]) + { + xVec3 sumTag = { 0, 0, 0 }; + + for (S32 i = 0; i < 4; i++) + { + iModelTagEval(sb1->m_subModels[3]->Data, &sb1->m_rightArmTags[i], + sb1->m_subModels[3]->Mat, &curTag); + xVec3Add(&sumTag, &sumTag, &curTag); + } + + xVec3SMulBy(&sumTag, 0.25f); + xVec3* pos = (xVec3*)&sSB1_Ptr->m_armTgt[1]->model->Mat->pos; + *pos = sumTag; + sSB1_Ptr->m_armTgt[1]->bound.sph.center = sumTag; + SB1Dummy_BoundFunc(sb1->m_armTgt[1], NULL); + } + } + + return this->xGoal::Process(trantype, dt, ctxt, scene); +} + +S32 zNPCGoalBossSB1Deflate::Enter(F32 dt, void* updCtxt) +{ + zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); + this->timeInGoal = 0.0f; + + RpGeometry* srcGeom; + RpGeometry* dstGeom; + xAnimState* deflateState; + + if (sSB1_armTgtHit == sb1->m_armTgt[0]) + { + srcGeom = sb1->m_subModels[2]->Data->geometry; + dstGeom = sb1->m_subModels[4]->Data->geometry; + deflateState = xAnimTableGetStateID(sb1->model->Anim->Table, g_hash_bossanim[SmashHitLeft]); + } + else + { + srcGeom = sb1->m_subModels[3]->Data->geometry; + dstGeom = sb1->m_subModels[5]->Data->geometry; + deflateState = + xAnimTableGetStateID(sb1->model->Anim->Table, g_hash_bossanim[SmashHitRight]); + } + + this->morphVertCount = srcGeom->numVertices; + this->modelVec = srcGeom->morphTarget->verts; + this->modelGeom = srcGeom; + this->targetVec = dstGeom->morphTarget->verts; + + memcpy(this->morphVertBuf, this->modelVec, this->morphVertCount * sizeof(RwV3d)); + + this->morphInvTime = 1.0f / (deflateState->Data->Duration - 0.05f); + + return this->zNPCGoalCommon::Enter(dt, updCtxt); +} + S32 zNPCGoalBossSB1Deflate::Exit(F32 dt, void* updCtxt) { zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); @@ -809,7 +913,7 @@ S32 zNPCGoalBossSB1Deflate::Exit(F32 dt, void* updCtxt) sb1->m_armColl[0]->model->Data = sb1->m_subModels[4]->Data; sb1->m_armColl[0]->model->Mat = sb1->m_subModels[4]->Mat; - sSB1_deflated[0] = 1; + sSB1_deflated[0] = true; } else { @@ -819,8 +923,39 @@ S32 zNPCGoalBossSB1Deflate::Exit(F32 dt, void* updCtxt) sb1->m_armColl[1]->model->Data = sb1->m_subModels[5]->Data; sb1->m_armColl[1]->model->Mat = sb1->m_subModels[5]->Mat; - sSB1_deflated[1] = 1; + sSB1_deflated[1] = true; } return this->zNPCGoalCommon::Exit(dt, updCtxt); } + +S32 zNPCGoalBossSB1Deflate::Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene) +{ + zNPCB_SB1* sb1 = (zNPCB_SB1*)this->GetOwner(); + + this->timeInGoal += dt; + + RpGeometryLock(this->modelGeom, 2); + F32 invlerp; + F32 lerp; + + lerp = this->timeInGoal * this->morphInvTime; + + if (lerp > 1.0f) + { + lerp = 1.0f; + } + + invlerp = 1.0f - lerp; + + for (S32 i = 0; i < this->morphVertCount; i++) + { + this->modelVec[i].x = invlerp * this->morphVertBuf[i].x + lerp * this->targetVec[i].x; + this->modelVec[i].y = invlerp * this->morphVertBuf[i].y + lerp * this->targetVec[i].y; + this->modelVec[i].z = invlerp * this->morphVertBuf[i].z + lerp * this->targetVec[i].z; + } + + RpGeometryUnlock(this->modelGeom); + + return this->xGoal::Process(trantype, dt, ctxt, scene); +} diff --git a/src/SB/Game/zNPCTypeBossSB1.h b/src/SB/Game/zNPCTypeBossSB1.h index 4bc0beb4..89c447eb 100644 --- a/src/SB/Game/zNPCTypeBossSB1.h +++ b/src/SB/Game/zNPCTypeBossSB1.h @@ -78,6 +78,7 @@ struct zNPCGoalBossSB1Smash : zNPCGoalCommon S32 Enter(F32 dt, void* updCtxt); S32 Exit(F32 dt, void* updCtxt); + S32 Process(en_trantype* trantype, F32 dt, void* ctxt, xScene* scene); }; struct zNPCGoalBossSB1Deflate : zNPCGoalCommon @@ -96,6 +97,7 @@ struct zNPCGoalBossSB1Deflate : zNPCGoalCommon S32 Enter(F32 dt, void* updCtxt); S32 Exit(F32 dt, void* updCtxt); + S32 Process(en_trantype* trantype, float dt, void* ctxt, xScene* scene); }; #endif diff --git a/src/SB/Game/zNPCTypeBossSB2.cpp b/src/SB/Game/zNPCTypeBossSB2.cpp index ed2ec492..aa229303 100644 --- a/src/SB/Game/zNPCTypeBossSB2.cpp +++ b/src/SB/Game/zNPCTypeBossSB2.cpp @@ -27,3 +27,8 @@ void zNPCB_SB2::decompose() void zNPCB_SB2::HoldUpDude() { } + +S32 zNPCGoalBossSB2Death::Process(en_trantype*, F32, void*, xScene*) +{ + return 0; +} diff --git a/src/SB/Game/zNPCTypeBossSB2.h b/src/SB/Game/zNPCTypeBossSB2.h index 00e5ab0c..408928ed 100644 --- a/src/SB/Game/zNPCTypeBossSB2.h +++ b/src/SB/Game/zNPCTypeBossSB2.h @@ -275,6 +275,7 @@ struct zNPCGoalBossSB2Death : zNPCGoalCommon zNPCB_SB2& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Process(en_trantype*, F32, void*, xScene*); }; #endif diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 74dc4dfe..f8ae72c7 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -7,6 +7,7 @@ #include "xEntDrive.h" #include "xBehaveMgr.h" #include "xEnt.h" +#include "xSFX.h" #include "zNPCSndTable.h" #include "zNPCSpawner.h" @@ -178,8 +179,8 @@ struct zNPCSettings : xDynAsset { en_npcbtyp basisType; S8 allowDetect; - S8 allowPatrol; - S8 allowWander; + U8 allowPatrol; + U8 allowWander; S8 reduceCollide; S8 useNavSplines; S8 pad[3]; @@ -401,12 +402,16 @@ struct zNPCCommon : xNPCBasic F32 AnimDuration(xAnimState* ast); bool IsMountableType(en_ZBASETYPE type); void MvptReset(zMovePoint* nav_goto); + S32 MvptCycle(); void ModelScaleSet(F32 x, F32 y, F32 z); void ModelScaleSet(F32 unk); void ModelScaleSet(const xVec3* vec); S32 AnimStart(U32 animID, S32 forceRestart); + xAnimState* AnimFindState(U32 animID); + xAnimState* AnimCurState(); U32 AnimCurStateID(); void GiveReward(); + S32 SndPlayFromSFX(xSFX* sfx, U32* sid_played); S32 SndPlayRandom(en_NPC_SOUND sndtype); S32 SndChanIsBusy(S32 flg_chan); S32 LassoUseGuides(S32 idx_grabmdl, S32 idx_holdmdl); diff --git a/src/SB/Game/zNPCTypeDutchman.cpp b/src/SB/Game/zNPCTypeDutchman.cpp index 96455e97..23297738 100644 --- a/src/SB/Game/zNPCTypeDutchman.cpp +++ b/src/SB/Game/zNPCTypeDutchman.cpp @@ -26,3 +26,28 @@ void zNPCDutchman::update_animation(float) void zNPCDutchman::add_splash(const xVec3&, float) { } + +U8 zNPCDutchman::PhysicsFlags() const +{ + return 3; +} + +U8 zNPCDutchman::ColPenByFlags() const +{ + return 16; +} + +U8 zNPCDutchman::ColChkByFlags() const +{ + return 16; +} + +U8 zNPCDutchman::ColPenFlags() const +{ + return 0; +} + +U8 zNPCDutchman::ColChkFlags() const +{ + return 0; +} diff --git a/src/SB/Game/zNPCTypeDutchman.h b/src/SB/Game/zNPCTypeDutchman.h index e8cc7c63..313f2fc5 100644 --- a/src/SB/Game/zNPCTypeDutchman.h +++ b/src/SB/Game/zNPCTypeDutchman.h @@ -140,6 +140,11 @@ struct zNPCDutchman : zNPCSubBoss void render_debug(); void update_animation(float); void add_splash(const xVec3&, float); + U8 PhysicsFlags() const; + U8 ColPenByFlags() const; + U8 ColChkByFlags() const; + U8 ColPenFlags() const; + U8 ColChkFlags() const; }; struct zNPCGoalDutchmanNil : zNPCGoalCommon diff --git a/src/SB/Game/zNPCTypePrawn.cpp b/src/SB/Game/zNPCTypePrawn.cpp index 43ffa82b..44bfc85f 100644 --- a/src/SB/Game/zNPCTypePrawn.cpp +++ b/src/SB/Game/zNPCTypePrawn.cpp @@ -13,3 +13,23 @@ void zNPCPrawn::update_particles(float) void xDebugAddTweak(const char*, xVec3*, const tweak_callback*, void*, U32) { } + +U8 zNPCPrawn::PhysicsFlags() const +{ + return 3; +} + +U8 zNPCPrawn::ColPenByFlags() const +{ + return 16; +} + +U8 zNPCPrawn::ColChkByFlags() const +{ + return 16; +} + +U8 zNPCPrawn::ColPenFlags() const +{ + return 0; +} diff --git a/src/SB/Game/zNPCTypePrawn.h b/src/SB/Game/zNPCTypePrawn.h index 0b57631a..e44a5a9a 100644 --- a/src/SB/Game/zNPCTypePrawn.h +++ b/src/SB/Game/zNPCTypePrawn.h @@ -134,6 +134,10 @@ struct zNPCPrawn : zNPCSubBoss zNPCPrawn(S32 myType); void render_debug(); void update_particles(float); + U8 PhysicsFlags() const; + U8 ColPenByFlags() const; + U8 ColChkByFlags() const; + U8 ColPenFlags() const; }; struct zNPCGoalPrawnIdle : zNPCGoalCommon diff --git a/src/SB/Game/zNPCTypeRobot.cpp b/src/SB/Game/zNPCTypeRobot.cpp index 7872fe3b..f92fff55 100644 --- a/src/SB/Game/zNPCTypeRobot.cpp +++ b/src/SB/Game/zNPCTypeRobot.cpp @@ -507,3 +507,73 @@ void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) o->y = y; o->z = z; } + +zNPCLassoInfo* zNPCFodBomb::PRIV_GetLassoData() +{ + return NULL; +} + +zNPCLassoInfo* zNPCFodBzzt::PRIV_GetLassoData() +{ + return NULL; +} + +zNPCLassoInfo* zNPCChomper::PRIV_GetLassoData() +{ + return NULL; +} + +zNPCLassoInfo* zNPCCritter::PRIV_GetLassoData() +{ + return NULL; +} + +zNPCLassoInfo* zNPCArfDog::PRIV_GetLassoData() +{ + return NULL; +} + +U8 zNPCTubeSlave::PhysicsFlags() const +{ + return 3; +} + +U8 zNPCTubeSlave::ColPenByFlags() const +{ + return 16; +} + +U8 zNPCTubeSlave::ColChkByFlags() const +{ + return 16; +} + +U8 zNPCTubeSlave::ColPenFlags() const +{ + return 0; +} + +U8 zNPCTubeSlave::ColChkFlags() const +{ + return 0; +} + +S32 zNPCTubeSlave::CanRope() +{ + return 0; +} + +U8 zNPCRobot::ColPenByFlags() const +{ + return 60; +} + +U8 zNPCRobot::ColChkByFlags() const +{ + return 60; +} + +U8 zNPCMonsoon::FoulWeather(F32) +{ + return 0; +} diff --git a/src/SB/Game/zNPCTypeRobot.h b/src/SB/Game/zNPCTypeRobot.h index 7086e9b1..4e99ddd2 100644 --- a/src/SB/Game/zNPCTypeRobot.h +++ b/src/SB/Game/zNPCTypeRobot.h @@ -43,6 +43,7 @@ struct NPCLaser F32 uv_base[2]; void ColorSet(const RwRGBA*, const RwRGBA*); + U32 TextureGet(); }; struct NPCBattle @@ -68,8 +69,8 @@ struct zNPCRobot : zNPCCommon zNPCRobot(S32); - S32 LaunchProjectile(en_npchaz haztyp, F32 spd_proj, F32 dst_minRange, - en_mdlvert idx_mvtx, F32 tym_predictMax, F32 hyt_offset); + S32 LaunchProjectile(en_npchaz haztyp, F32 spd_proj, F32 dst_minRange, en_mdlvert idx_mvtx, + F32 tym_predictMax, F32 hyt_offset); void ShowerConfetti(xVec3* pos); F32 MoveTowardsArena(F32 dt, F32 speed); void CornerOfArena(xVec3* pos_corner, F32 dst); @@ -79,8 +80,7 @@ struct zNPCRobot : zNPCCommon void InflictPain(S32 numHitPoints, S32 giveCreditToPlayer); void LassoNotify(en_LASSO_EVENT event); void SyncStunGlyph(F32 tmr_remain, F32 height); - void AddStunThrow(xPsyche* psy, - S32 (*eval_evilpat)(xGoal*, void*, en_trantype*, F32, void*), + void AddStunThrow(xPsyche* psy, S32 (*eval_evilpat)(xGoal*, void*, en_trantype*, F32, void*), S32 (*eval_stunned)(xGoal*, void*, en_trantype*, F32, void*), S32 (*eval_patcarry)(xGoal*, void*, en_trantype*, F32, void*), S32 (*eval_patthrow)(xGoal*, void*, en_trantype*, F32, void*)); @@ -111,7 +111,7 @@ struct zNPCRobot : zNPCCommon void Process(xScene* xscn, F32 dt); void NewTime(xScene* xscn, F32 dt); S32 SysEvent(xBase* from, xBase* to, U32 toEvent, F32* toParam, xBase* toParamWidget, - S32* handled); + S32* handled); void CollideReview(); U8 PhysicsFlags() const; U8 ColPenFlags() const; @@ -136,6 +136,8 @@ struct zNPCRobot : zNPCCommon void Stun(F32 stuntime); F32 GenShadCacheRad(); xEntDrive* PRIV_GetDriverData(); + U8 ColPenByFlags() const; + U8 ColChkByFlags() const; zNPCLassoInfo* PRIV_GetLassoData(); S32 LassoSetup(); @@ -164,6 +166,7 @@ struct zNPCFodBomb : zNPCRobot NPCBlinker blinker; zNPCFodBomb(S32 myType); + zNPCLassoInfo* PRIV_GetLassoData(); }; struct zNPCFodBzzt : zNPCRobot @@ -174,6 +177,7 @@ struct zNPCFodBzzt : zNPCRobot F32 uv_discoLight[2]; zNPCFodBzzt(S32 myType); + zNPCLassoInfo* PRIV_GetLassoData(); }; struct zNPCChomper : zNPCRobot @@ -182,11 +186,13 @@ struct zNPCChomper : zNPCRobot S32 cnt_skipEmit; zNPCChomper(S32 myType); + zNPCLassoInfo* PRIV_GetLassoData(); }; struct zNPCCritter : zNPCRobot { zNPCCritter(S32 myType); + zNPCLassoInfo* PRIV_GetLassoData(); }; struct zNPCHammer : zNPCRobot @@ -207,6 +213,7 @@ struct zNPCGlove : zNPCRobot struct zNPCMonsoon : zNPCRobot { zNPCMonsoon(S32 myType); + U8 FoulWeather(float); }; struct zNPCSleepy : zNPCRobot @@ -228,6 +235,7 @@ struct zNPCArfDog : zNPCRobot NPCBlinker blinkTail; zNPCArfDog(S32 myType); + zNPCLassoInfo* PRIV_GetLassoData(); }; struct zNPCArfArf : zNPCRobot @@ -244,6 +252,62 @@ struct zNPCChuck : zNPCRobot xVec3 dir_attack; zNPCChuck(S32 myType); + // 0x00000000; // 0x0 + // 0x00000000; // 0x4 + /* + Init(xEntAsset*); // 0x8 zNPCChuck + PostInit(); // 0xC xNPCBasic + Setup(); // 0x10 zNPCCommon + PostSetup(); // 0x14 xNPCBasic + Reset(); // 0x18 zNPCChuck + Process(xScene*, float); // 0x1C zNPCRobot + BUpdate(xVec3*); // 0x20 zNPCCommon + NewTime(xScene*, float); // 0x24 zNPCRobot + Move(xScene*, float, xEntFrame*); // 0x28 zNPCCommon + SysEvent(xBase*, xBase*, unsigned int, const float*, xBase*, int*); // 0x2C zNPCRobot + Render(); // 0x30 xNPCBasic + Save(xSerial*) const; // 0x34 xNPCBasic + Load(xSerial*); // 0x38 xNPCBasic + CollideReview(); // 0x3C zNPCRobot + ColChkFlags() const; // 0x40 zNPCRobot + ColPenFlags() const; // 0x44 zNPCRobot + ColChkByFlags() const; // 0x48 zNPCRobot + ColPenByFlags() const; // 0x4C zNPCRobot + PhysicsFlags() const; // 0x50 zNPCRobot + Destroy(); // 0x54 zNPCCommon + NPCMessage(NPCMsg*); // 0x58 zNPCRobot + RenderExtra(); // 0x5C zNPCCommon + RenderExtraPostParticles(); // 0x60 zNPCCommon + ParseINI(); // 0x64 zNPCChuck + ParseLinks(); // 0x68 zNPCCommon + ParseProps(); // 0x6C zNPCCommon + SelfSetup(); // 0x70 zNPCChuck + SelfDestroy(); // 0x74 zNPCCommon + IsHealthy(); // 0x78 zNPCRobot + IsAlive(); // 0x7C zNPCRobot + Damage(en_NPC_DAMAGE_TYPE, xBase*, const xVec3*); // 0x80 zNPCCommon + Respawn(const xVec3*, zMovePoint*, zMovePoint*); // 0x84 zNPCCommon + DuploOwner(zNPCCommon*); // 0x88 zNPCRobot + DuploNotice(en_SM_NOTICES, void*); // 0x8C zNPCCommon + CanRope(); // 0x90 zNPCCommon + LassoNotify(en_LASSO_EVENT); // 0x94 zNPCRobot + SetCarryState(en_NPC_CARRY_STATE); // 0x98 zNPCRobot + Stun(float); // 0x9C zNPCRobot + SpeakBegin(); // 0xA0 zNPCCommon + SpeakEnd(); // 0xA4 zNPCCommon + SpeakStart(unsigned int, unsigned int, int); // 0xA8 zNPCCommon + SpeakStop(); // 0xAC zNPCCommon + AnimPick(int, en_NPC_GOAL_SPOT, xGoal*); // 0xB0 zNPCChuck + GetParm(en_npcparm, void*); // 0xB4 zNPCCommon + GetParmDefault(en_npcparm, void*); // 0xB8 zNPCCommon + GenShadCacheRad(); // 0xBC zNPCRobot + PRIV_GetDriverData(); // 0xC0 zNPCRobot + PRIV_GetLassoData(); // 0xC4 zNPCRobot + LassoSetup(); // 0xC8 zNPCRobot + RoboHandleMail(NPCMsg*); // 0xCC zNPCRobot + IsDying(); // 0xD0 zNPCRobot + LassoModelIndex(int*, int*); // 0xD4 zNPCChuck + */ }; enum en_tubestat @@ -298,6 +362,12 @@ struct zNPCTubeSlave : zNPCRobot zNPCTubelet* tub_pete; zNPCTubeSlave(S32 myType); + U8 PhysicsFlags() const; + U8 ColPenByFlags() const; + U8 ColChkByFlags() const; + U8 ColPenFlags() const; + U8 ColChkFlags() const; + S32 CanRope(); }; struct zNPCSlick : zNPCRobot diff --git a/src/SB/Game/zNPCTypeTiki.cpp b/src/SB/Game/zNPCTypeTiki.cpp index c12c40e4..d9038742 100644 --- a/src/SB/Game/zNPCTypeTiki.cpp +++ b/src/SB/Game/zNPCTypeTiki.cpp @@ -30,6 +30,31 @@ void ZNPC_Tiki_Startup() } } +U8 zNPCTiki::ColPenByFlags() const +{ + return 24; +} + +U8 zNPCTiki::PhysicsFlags() const +{ + return 0; +} + +U8 zNPCTiki::ColChkByFlags() const +{ + return 24; +} + +U8 zNPCTiki::ColPenFlags() const +{ + return 0; +} + +U8 zNPCTiki::ColChkFlags() const +{ + return 0; +} + void ZNPC_Tiki_Shutdown() { } diff --git a/src/SB/Game/zNPCTypeTiki.h b/src/SB/Game/zNPCTypeTiki.h index f6a8c246..72a7eadd 100644 --- a/src/SB/Game/zNPCTypeTiki.h +++ b/src/SB/Game/zNPCTypeTiki.h @@ -17,39 +17,44 @@ struct zNPCTiki : zNPCCommon F32 t3; xVec3 v1; F32 vel; - F32 landHt; // 0x328 - xEnt *nonTikiParent; // 0x32c + F32 landHt; // 0x328 + xEnt* nonTikiParent; // 0x32c xVec3 nonTikiParentDisp; // 0x330 - U8 numParents; // 0x33c - zNPCTiki *parents[4]; // 0x340 + U8 numParents; // 0x33c + zNPCTiki* parents[4]; // 0x340 U8 numChildren; - zNPCTiki *children[4]; - zNPCTiki *nextOrphan; // 0x364 + zNPCTiki* children[4]; + zNPCTiki* nextOrphan; // 0x364 U32 updatedParents; S32 contactParent; - void *tikiAnim; + void* tikiAnim; F32 tikiAnimTime; zNPCTiki(S32); void RemoveFromFamily(); - void FindParents(zScene *zsc); + void FindParents(zScene* zsc); - void Init(xEntAsset *entass); + void Init(xEntAsset* entass); void Reset(); void Setup(); - void Process(xScene *xscn, F32 dt); - void BUpdate(xVec3 *pos); - virtual void Move(xScene *xscn, F32 dt, xEntFrame *); - S32 SysEvent(xBase *from, xBase *to, U32 toEvent, F32 *toParam, xBase *toParamWidget, - S32 *handled); + void Process(xScene* xscn, F32 dt); + void BUpdate(xVec3* pos); + virtual void Move(xScene* xscn, F32 dt, xEntFrame*); + S32 SysEvent(xBase* from, xBase* to, U32 toEvent, F32* toParam, xBase* toParamWidget, + S32* handled); void ParseINI(); void SelfSetup(); S32 IsHealthy(); virtual S32 IsAlive(); - virtual void Damage(en_NPC_DAMAGE_TYPE damtype, xBase *who, const xVec3 *vec_hit); - virtual S32 Respawn(xVec3 *pos, zMovePoint *mvptFirst, zMovePoint *mvptSpawnRef); - virtual void DuploOwner(zNPCCommon *duper); + U8 PhysicsFlags() const; + U8 ColChkByFlags() const; + U8 ColPenFlags() const; + U8 ColChkFlags() const; + U8 ColPenByFlags() const; + virtual void Damage(en_NPC_DAMAGE_TYPE damtype, xBase* who, const xVec3* vec_hit); + virtual S32 Respawn(xVec3* pos, zMovePoint* mvptFirst, zMovePoint* mvptSpawnRef); + virtual void DuploOwner(zNPCCommon* duper); virtual void DuploNotice(); virtual S32 CanRope(); S32 SetCarryState(en_NPC_CARRY_STATE cs); @@ -58,10 +63,10 @@ struct zNPCTiki : zNPCCommon void ZNPC_Tiki_Startup(); void ZNPC_Tiki_Shutdown(); -void zNPCTiki_InitStacking(zScene *zsc); -void zNPCTiki_InitFX(zScene *); -void zNPCTiki_ExplodeFX(zNPCTiki *tiki); -xFactoryInst *ZNPC_Create_Tiki(S32 who, RyzMemGrow *grow, void *); -void ZNPC_Destroy_Tiki(xFactoryInst *inst); +void zNPCTiki_InitStacking(zScene* zsc); +void zNPCTiki_InitFX(zScene*); +void zNPCTiki_ExplodeFX(zNPCTiki* tiki); +xFactoryInst* ZNPC_Create_Tiki(S32 who, RyzMemGrow* grow, void*); +void ZNPC_Destroy_Tiki(xFactoryInst* inst); #endif diff --git a/src/SB/Game/zNPCTypeVillager.cpp b/src/SB/Game/zNPCTypeVillager.cpp index 2cd49260..9e2333f0 100644 --- a/src/SB/Game/zNPCTypeVillager.cpp +++ b/src/SB/Game/zNPCTypeVillager.cpp @@ -191,3 +191,53 @@ void ztaskbox::callback::on_talk_start() void ztaskbox::callback::on_talk_stop() { } + +U8 zNPCNewsFishTV::PhysicsFlags() const +{ + return 0; +} + +U8 zNPCNewsFishTV::ColPenByFlags() const +{ + return 0; +} + +U8 zNPCNewsFishTV::ColChkByFlags() const +{ + return 0; +} + +U8 zNPCNewsFishTV::ColPenFlags() const +{ + return 0; +} + +U8 zNPCNewsFishTV::ColChkFlags() const +{ + return 0; +} + +U8 zNPCMerManChair::PhysicsFlags() const +{ + return 0; +} + +U8 zNPCMerManChair::ColPenFlags() const +{ + return 0; +} + +U8 zNPCMerManChair::ColChkFlags() const +{ + return 0; +} + +U8 zNPCVillager::ColPenByFlags() const +{ + return 24; +} + +U8 zNPCVillager::ColChkByFlags() const +{ + return 24; +} diff --git a/src/SB/Game/zNPCTypeVillager.h b/src/SB/Game/zNPCTypeVillager.h index d8951f4c..a86b76ba 100644 --- a/src/SB/Game/zNPCTypeVillager.h +++ b/src/SB/Game/zNPCTypeVillager.h @@ -22,6 +22,11 @@ struct zNPCVillager : zNPCCommon S32 current_talk_anim; zNPCVillager(S32 myType); + + void FindMyConverse(); + U8 ColPenByFlags() const; + U8 ColChkByFlags() const; + F32 GenShadCacheRad(); }; struct zNPCFish : zNPCVillager @@ -40,6 +45,14 @@ struct zNPCBubbleBuddy : zNPCFish zNPCBubbleBuddy(S32 myType); }; +enum en_BBOY_PLATANIM +{ + BBOY_PLATANIM_MOVE, + BBOY_PLATANIM_HIT, + BBOY_PLATANIM_NOMORE, + BBOY_PLATANIM_FORCE = 0x7FFFFFFF, +}; + struct zNPCBalloonBoy : zNPCFish { S32 specialBalloon; @@ -47,6 +60,9 @@ struct zNPCBalloonBoy : zNPCFish xShadowCache* shadCache; zNPCBalloonBoy(S32 myType); + + void PlatAnimSet(en_BBOY_PLATANIM anim); + void PlatAnimSync(); }; struct zNPCSandyBikini : zNPCVillager @@ -61,6 +77,9 @@ struct zNPCMerManChair : zNPCVillager S32 flg_mermanchair; zNPCMerManChair(S32 myType); + U8 PhysicsFlags() const; + U8 ColPenFlags() const; + U8 ColChkFlags() const; }; struct zNPCNewsFish : zNPCVillager @@ -89,12 +108,72 @@ struct zNPCNewsFish : zNPCVillager F32 screenLerp; zNPCNewsFish(S32 myType); - void SelfSetup(); + + // Vtable Information + // 0x00000000; // 0x0 + // 0x00000000; // 0x4 + void Init(xEntAsset*); // 0x8 zNPCNewsFish + void PostInit(); // 0xC xNPCBasic + void Setup(); // 0x10 zNPCCommon + void PostSetup(); // 0x14 zNPCNewsFish + void Reset(); // 0x18 zNPCNewsFish + void Process(xScene*, F32); // 0x1C zNPCNewsFish + void BUpdate(xVec3*); // 0x20 zNPCCommon + void NewTime(xScene*, F32); // 0x24 zNPCCommon + void Move(xScene*, F32, xEntFrame*); // 0x28 zNPCCommon + S32 SysEvent(xBase*, xBase*, U32, const F32*, xBase*, S32*); // 0x2C zNPCCommon + void Render(); // 0x30 zNPCNewsFish + void Save(xSerial*) const; // 0x34 xNPCBasic + void Load(xSerial*); // 0x38 xNPCBasic + void CollideReview(); // 0x3C zNPCVillager + U8 ColChkFlags() const; // 0x40 zNPCVillager + U8 ColPenFlags() const; // 0x44 zNPCVillager + U8 ColChkByFlags() const; // 0x48 zNPCVillager + U8 ColPenByFlags() const; // 0x4C zNPCVillager + U8 PhysicsFlags() const; // 0x50 zNPCVillager + void Destroy(); // 0x54 zNPCCommon + S32 NPCMessage(NPCMsg*); // 0x58 zNPCVillager + void RenderExtra(); // 0x5C zNPCCommon + void RenderExtraPostParticles(); // 0x60 zNPCCommon + void ParseINI(); // 0x64 zNPCVillager + void ParseLinks(); // 0x68 zNPCCommon + void ParseProps(); // 0x6C zNPCCommon + void SelfSetup(); // 0x70 zNPCNewsFish + void SelfDestroy(); // 0x74 zNPCCommon + S32 IsHealthy(); // 0x78 zNPCCommon + S32 IsAlive(); // 0x7C zNPCCommon + void Damage(en_NPC_DAMAGE_TYPE, xBase*, const xVec3*); // 0x80 zNPCCommon + S32 Respawn(const xVec3*, zMovePoint*, zMovePoint*); // 0x84 zNPCCommon + void DuploOwner(zNPCCommon*); // 0x88 zNPCCommon + void DuploNotice(en_SM_NOTICES, void*); // 0x8C zNPCCommon + S32 CanRope(); // 0x90 zNPCCommon + void LassoNotify(en_LASSO_EVENT); // 0x94 zNPCCommon + S32 SetCarryState(en_NPC_CARRY_STATE); // 0x98 zNPCCommon + void Stun(F32); // 0x9C zNPCCommon + void SpeakBegin(); // 0xA0 zNPCVillager + void SpeakEnd(); // 0xA4 zNPCVillager + void SpeakStart(U32 sndid, U32 sndhandle, S32 anim); // 0xA8 zNPCNewsFish + void SpeakStop(); // 0xAC zNPCNewsFish + U32 AnimPick(S32, en_NPC_GOAL_SPOT, xGoal*); // 0xB0 zNPCVillager + void GetParm(en_npcparm, void*); // 0xB4 zNPCCommon + void GetParmDefault(en_npcparm, void*); // 0xB8 zNPCCommon + F32 GenShadCacheRad(); // 0xBC zNPCVillager + xEntDrive* PRIV_GetDriverData(); // 0xC0 zNPCCommon + zNPCLassoInfo* PRIV_GetLassoData(); // 0xC4 zNPCCommon + S32 LassoSetup(); // 0xC8 zNPCCommon + void FolkHandleMail(NPCMsg*); // 0xCC zNPCVillager + + void TalkOnScreen(S32 talkOnScreen); }; struct zNPCNewsFishTV : zNPCVillager { zNPCNewsFishTV(S32 myType); + U8 PhysicsFlags() const; + U8 ColPenByFlags() const; + U8 ColChkByFlags() const; + U8 ColPenFlags() const; + U8 ColChkFlags() const; }; xAnimTable* ZNPC_AnimTable_Villager(xAnimTable* callerTable); diff --git a/src/SB/Game/zPlatform.h b/src/SB/Game/zPlatform.h index be15c913..51062dfb 100644 --- a/src/SB/Game/zPlatform.h +++ b/src/SB/Game/zPlatform.h @@ -133,7 +133,7 @@ struct zPlatFMRunTime struct zPlatform : zEnt { - xPlatformAsset* passet; + xPlatformAsset* passet; // 0xD4 xEntMotion motion; U16 state; U16 plat_flags; @@ -169,6 +169,6 @@ void zPlatform_Save(zPlatform* ent, xSerial* s); void zPlatform_Load(zPlatform* ent, xSerial* s); void zPlatform_Reset(zPlatform* plat, xScene* sc); U32 zPlatform_PaddleCollide(xCollis* coll, const xVec3* hitsource, const xVec3* hitvel, - U32 worldSpaceNorm); + U32 worldSpaceNorm); #endif diff --git a/src/SB/Game/zSurface.h b/src/SB/Game/zSurface.h index d2f5a3a5..68b11852 100644 --- a/src/SB/Game/zSurface.h +++ b/src/SB/Game/zSurface.h @@ -2,6 +2,7 @@ #define ZSURFACE_H #include "xBase.h" +#include "xCollide.h" #include "xMath3.h" #include "xSurface.h" @@ -121,7 +122,7 @@ struct xScene; void zSurfaceRegisterMapper(U32 assetId); void zSurfaceExit(); xSurface* zSurfaceGetSurface(U32 mat_id); -// xSurface* zSurfaceGetSurface(const xCollis* coll); +xSurface* zSurfaceGetSurface(const xCollis* coll); U32 zSurfaceGetStandOn(const xSurface* surf); void zSurfaceSave(xSurface* ent, xSerial* s); void zSurfaceLoad(xSurface* ent, xSerial* s); diff --git a/src/SB/Game/zThrown.h b/src/SB/Game/zThrown.h index 3fde6023..b31452a2 100644 --- a/src/SB/Game/zThrown.h +++ b/src/SB/Game/zThrown.h @@ -67,12 +67,12 @@ void zThrownCollide_DestructObj(zThrownStruct* thrown, xEntCollis* collis, F32* F32* friction); void zThrownCollide_BSandyHead(zThrownStruct* thrown, xEntCollis* collis, F32* bounce, F32* friction); -void zThrownCollide_Tiki(zThrownStruct* thrown, xEntCollis* collis, F32* bounce, - F32* friction); +void zThrownCollide_Tiki(zThrownStruct* thrown, xEntCollis* collis, F32* bounce, F32* friction); +void zThrown_AddFruit(xEnt* ent); S32 zThrown_IsFruit(xEnt* ent, F32* stackHeight); void checkAgainstButtons(xEnt* ent); xBase* zThrown_ButtonIteratorCB(xBase* b, zScene* scn, void* user); -void xDrawSphere(xSphere* s, U32 unk); +void xDrawSphere(const xSphere* s, U32 unk); S32 zThrown_KillFruit(xEnt* ent); void zThrown_LaunchDir(xEnt* ent, xVec3* dir); diff --git a/tools/report.py b/tools/report.py new file mode 100644 index 00000000..5a626ef2 --- /dev/null +++ b/tools/report.py @@ -0,0 +1,21 @@ +from pathlib import Path +import shutil +import subprocess +from pygit2 import GIT_CHECKOUT_FORCE, Repository + +repo = Repository(".") +branch = repo.lookup_branch("main") +ref = repo.lookup_reference(branch.name) +repo.checkout(ref, strategy=GIT_CHECKOUT_FORCE) + +for commit in list(repo.walk(repo.head.target)): + id = str(commit.id) + shutil.rmtree("./build", ignore_errors=True) + filename = f"./artifacts/{id}.json" + if (not Path(filename).is_file()): + repo.checkout_tree(commit, strategy=GIT_CHECKOUT_FORCE) + subprocess.run("ninja all_source", shell=True) + subprocess.run(f"./objdiff-cli report generate -o {filename}", shell=True) + else: + print("skipping " + filename) + print(commit.id)