From 3d9bb60f1da82b086736f40f23e05fe6e80b8fa9 Mon Sep 17 00:00:00 2001 From: escape209 Date: Sun, 15 Sep 2024 20:16:19 +0100 Subject: [PATCH] Assorted matches, including ports from rat (#367) zNPC related matches More stuff --- src/SB/Core/gc/iColor.h | 9 + src/SB/Core/gc/iMorph.h | 8 + src/SB/Core/x/xDebug.cpp | 14 +- src/SB/Core/x/xFX.h | 1 + src/SB/Core/x/xFont.h | 17 ++ src/SB/Core/x/xMorph.cpp | 121 +++++++++- src/SB/Core/x/xMorph.h | 43 ++++ src/SB/Core/x/xMovePoint.cpp | 38 +++- src/SB/Core/x/xPad.cpp | 32 +++ src/SB/Core/x/xPad.h | 2 + src/SB/Core/x/xRenderState.cpp | 5 +- src/SB/Core/x/xSpline.h | 3 + src/SB/Core/x/xTimer.cpp | 16 ++ src/SB/Game/zMusic.cpp | 3 - src/SB/Game/zNPCGoalRobo.cpp | 379 ++++++++++++++++++++++++++++++- src/SB/Game/zNPCGoalStd.h | 62 ++++- src/SB/Game/zNPCGoalVillager.cpp | 16 +- src/SB/Game/zNPCSupport.h | 11 + src/SB/Game/zNPCTypeCommon.h | 1 + src/SB/Game/zNPCTypeRobot.h | 1 + 20 files changed, 750 insertions(+), 32 deletions(-) diff --git a/src/SB/Core/gc/iColor.h b/src/SB/Core/gc/iColor.h index d7b0baf35..c01e8ba4d 100644 --- a/src/SB/Core/gc/iColor.h +++ b/src/SB/Core/gc/iColor.h @@ -9,6 +9,15 @@ struct iColor_tag U8 g; U8 b; U8 a; + + iColor_tag& operator=(const iColor_tag& rhs) + { + this->r = rhs.r; + this->g = rhs.g; + this->b = rhs.b; + this->a = rhs.a; + return *this; + }; }; #endif diff --git a/src/SB/Core/gc/iMorph.h b/src/SB/Core/gc/iMorph.h index 292a0ab74..a3b033333 100644 --- a/src/SB/Core/gc/iMorph.h +++ b/src/SB/Core/gc/iMorph.h @@ -1,4 +1,12 @@ #ifndef IMORPH_H #define IMORPH_H +#include "types.h" + +#include +#include + +void iMorphOptimize(RpAtomic* model, S32 normals); +void iMorphRender(RpAtomic* model, RwMatrix* mat, S16** v_array, S16* weight, U32 normals, F32 scale); + #endif \ No newline at end of file diff --git a/src/SB/Core/x/xDebug.cpp b/src/SB/Core/x/xDebug.cpp index 7a091e4cf..1d0a099b9 100644 --- a/src/SB/Core/x/xDebug.cpp +++ b/src/SB/Core/x/xDebug.cpp @@ -1,18 +1,20 @@ #include "xDebug.h" +#include "xFont.h" + +#include "iColor.h" #include U32 gFrameCount; -extern F32 _781; // 0.0020833334f. -extern F32 _783; // 0.0015625f. +// Remaining weak definitions will match once referenced e.g. iColor_tag::operator= void xprintf(const char* msg, ...) { // Redacted. :} } -S32 xDebugModeAdd(char* mode, void(*debugFunc)) +S32 xDebugModeAdd(const char* mode, void(*debugFunc)()) { // Redacted. :} return -1; @@ -45,10 +47,10 @@ void xtextbox::render(bool cache) const F32 NSCREENY(F32 scale) { - return _781 * scale; + return (1.0f / 480) * scale; } F32 NSCREENX(F32 scale) { - return _783 * scale; -} + return (1.0f / 640) * scale; +} \ No newline at end of file diff --git a/src/SB/Core/x/xFX.h b/src/SB/Core/x/xFX.h index 855fc1197..18bbc9abf 100644 --- a/src/SB/Core/x/xFX.h +++ b/src/SB/Core/x/xFX.h @@ -109,6 +109,7 @@ void xFXFireworksUpdate(F32 dt); void xFXStreakInit(); void xFXStreakUpdate(F32 dt); void xFXStreakRender(); +void xFXStreakStop(U32); void xFXShineInit(); void xFXShineUpdate(F32 dt); void xFXShineRender(); diff --git a/src/SB/Core/x/xFont.h b/src/SB/Core/x/xFont.h index fcd228a03..055fa11fa 100644 --- a/src/SB/Core/x/xFont.h +++ b/src/SB/Core/x/xFont.h @@ -32,6 +32,23 @@ struct xfont void irender(const char* text, F32 x, F32 y) const; void irender(const char* text, size_t text_size, F32 x, F32 y) const; void render(const char* text, F32 x, F32 y) const; + + xfont& operator=(const xfont& rhs) + { + id = rhs.id; + width = rhs.width; + height = rhs.height; + space = rhs.space; + + *(U32*)(&color) = *(U32*)(&rhs.color); + + *(U32*)(&clip.x) = *(U32*)(&rhs.clip.x); + *(U32*)(&clip.y) = *(U32*)(&rhs.clip.y); + *(U32*)(&clip.w) = *(U32*)(&rhs.clip.w); + *(U32*)(&clip.h) = *(U32*)(&rhs.clip.h); + + return *this; + } }; struct xtextbox diff --git a/src/SB/Core/x/xMorph.cpp b/src/SB/Core/x/xMorph.cpp index 2c9775b16..ad2f91bc7 100644 --- a/src/SB/Core/x/xMorph.cpp +++ b/src/SB/Core/x/xMorph.cpp @@ -1,3 +1,122 @@ #include "xMorph.h" -#include +#include "xDebug.h" +#include "iModel.h" + +#include + +xMorphSeqFile* xMorphSeqSetup(void* data, xMorphFindAssetCallback FindAssetCB) +{ + S32 i, j; + RpAtomic* model; + xMorphTargetFile* mphtgt; + xMorphSeqFile* header; + F32* timelist; + xMorphFrame* framelist; + U32* assetlist; + char* namelist; + void* assetPtr; + U32 skipsize; + + header = (xMorphSeqFile*)data; + timelist = (F32*)(header + 1); + framelist = (xMorphFrame*)(timelist + header->TimeCount); + assetlist = (U32*)(framelist + header->TimeCount); + namelist = (char*)(assetlist + header->ModelCount * 2); + + if (header->Flags & 0x80000000) { + return header; + } + + header->Flags |= 0x80000000; + if (!(header->Flags & 0x1)) { + namelist = NULL; + } + + for (i = 0; i < (S32)header->ModelCount * 2; i++) { + if (assetlist[i]) { + assetPtr = FindAssetCB(assetlist[i], namelist); + assetlist[i] = (U32)assetPtr; + } + if (namelist) { + namelist = strlen(namelist) + 1 + namelist; + } + } + + for (i = 0; i < (S32)header->ModelCount; i++) { + if (assetlist[i*2+1]) { + model = (RpAtomic*)assetlist[i*2]; + mphtgt = (xMorphTargetFile*)assetlist[i*2+1]; + iMorphOptimize(model, mphtgt->Flags & 0x1); + } + } + + for (i = 0; i < (S32)header->TimeCount; i++) { + model = (RpAtomic*)assetlist[(U32)framelist[i].Model*2]; + mphtgt = (xMorphTargetFile*)assetlist[(U32)framelist[i].Model*2+1]; + framelist[i].Model = model; + for (j = 0; j < 4; j++) { + if ((U32)framelist[i].Targets[j] + 0x10000 == 0xFFFF) { + framelist[i].Targets[j] = NULL; + } else { + skipsize = (mphtgt->NumVerts * 3 + 7) & ~7; + if (mphtgt->Flags & 0x1) { + skipsize *= 2; + } + if (j == 0) { + framelist[i].Flags = mphtgt->Flags; + framelist[i].NumVerts = mphtgt->NumVerts; + framelist[i].Scale *= mphtgt->Scale; + } + framelist[i].Targets[j] = (S16*)((U8*)(mphtgt + 1) + skipsize * (U32)framelist[i].Targets[j] * 2); + } + } + } + + return header; +} + +void xMorphRender(xMorphSeqFile* seq, RwMatrix* mat, F32 time) +{ + F32 lerp; + U32 tidx, tcount; + S16 weight[4]; + S16* wptr; + F32* times; + xMorphFrame* frame; + + times = (F32*)(seq + 1); + tcount = seq->TimeCount; + frame = (xMorphFrame*)(times + seq->TimeCount); + + if (time < 0.0f) time = 0.0f; + if (time > times[tcount-1]) time = times[tcount-1]; + + tidx = (tcount-1) & 0x3; + while (times[tidx] < time) tidx += 4; + while (tidx && time < times[tidx]) tidx--; + + frame += tidx; + + if (!frame->Targets[0]) { + iModelRender(frame->Model, mat); + } else { + lerp = frame->RecipTime * (time - times[tidx]); + if (lerp == 0.0f) { + wptr = frame->WeightStart; + } else { + weight[0] = (S32)(lerp * (frame->WeightEnd[0] - frame->WeightStart[0])) + frame->WeightStart[0], + weight[1] = (S32)(lerp * (frame->WeightEnd[1] - frame->WeightStart[1])) + frame->WeightStart[1], + weight[2] = (S32)(lerp * (frame->WeightEnd[2] - frame->WeightStart[2])) + frame->WeightStart[2], + weight[3] = (S32)(lerp * (frame->WeightEnd[3] - frame->WeightStart[3])) + frame->WeightStart[3]; + wptr = weight; + } + + iMorphRender(frame->Model, mat, frame->Targets, wptr, frame->Flags & 0x1, frame->Scale); + } +} + +F32 xMorphSeqDuration(xMorphSeqFile* seq) +{ + return ((F32*)(seq+1))[seq->TimeCount-1]; +} diff --git a/src/SB/Core/x/xMorph.h b/src/SB/Core/x/xMorph.h index 7439a9f46..3ee24ac1c 100644 --- a/src/SB/Core/x/xMorph.h +++ b/src/SB/Core/x/xMorph.h @@ -1,4 +1,47 @@ #ifndef XMORPH_H #define XMORPH_H +#include "iMorph.h" +#include "xMath3.h" + +#include +#include + +struct xMorphSeqFile +{ + U32 Magic; + U32 Flags; + U32 TimeCount; + U32 ModelCount; +}; + +struct xMorphFrame +{ + RpAtomic* Model; + F32 RecipTime; + F32 Scale; + U16 Flags; + U16 NumVerts; + S16* Targets[4]; + S16 WeightStart[4]; + S16 WeightEnd[4]; +}; + +struct xMorphTargetFile +{ + U32 Magic; + U16 NumTargets; + U16 NumVerts; + U32 Flags; + F32 Scale; + xVec3 Center; + F32 Radius; +}; + +typedef void*(*xMorphFindAssetCallback)(U32, char*); + +xMorphSeqFile* xMorphSeqSetup(void* data, xMorphFindAssetCallback FindAssetCB); +void xMorphRender(xMorphSeqFile* seq, RwMatrix* mat, F32 time); +F32 xMorphSeqDuration(xMorphSeqFile* seq); + #endif \ No newline at end of file diff --git a/src/SB/Core/x/xMovePoint.cpp b/src/SB/Core/x/xMovePoint.cpp index 07d88fbfe..9a52c740b 100644 --- a/src/SB/Core/x/xMovePoint.cpp +++ b/src/SB/Core/x/xMovePoint.cpp @@ -68,6 +68,42 @@ void xMovePointSplineDestroy(xMovePoint* m) } } +void xMovePointSplineSetup(xMovePoint* m) +{ + xMovePoint* w0, *w1, *w2, *w3; + xVec3 points[2]; + xVec3 p1, p2; + + if (m->asset->bezIndex != 1) return; + if (m->spl) return; + + w0 = m->prev; + w1 = m; + w2 = m->nodes[0]; + + points[0] = *w0->pos; + if (w2->asset->bezIndex > 0) + { + w3 = w2->nodes[0]; + p1 = *w1->pos; + p2 = *w2->pos; + points[1] = *w3->pos; + } + else + { + p1.x = (1/3.f) * w0->pos->x + (2/3.f) * w1->pos->x; + p1.y = (1/3.f) * w0->pos->y + (2/3.f) * w1->pos->y; + p1.z = (1/3.f) * w0->pos->z + (2/3.f) * w1->pos->z; + p2.x = (2/3.f) * w1->pos->x + (1/3.f) * w2->pos->x; + p2.y = (2/3.f) * w1->pos->y + (1/3.f) * w2->pos->y; + p2.z = (2/3.f) * w1->pos->z + (1/3.f) * w2->pos->z; + points[1] = *w2->pos; + } + + m->spl = xSpline3_Bezier(points, NULL, 2, 0, &p1, &p2); + xSpline3_ArcInit(m->spl, 20); +} + #if 0 // If you uncomment the numPoints variable then this function is a perfect match // minus ordering. In the original assembly some variable fetches are lifted to @@ -138,7 +174,7 @@ F32 xMovePointGetNext(xMovePoint* m, xMovePoint* prev, xMovePoint** next, xVec3* } #endif -xVec3* xMovePointGetPos(xMovePoint* m) +xVec3* xMovePointGetPos(const xMovePoint* m) { return m->pos; } diff --git a/src/SB/Core/x/xPad.cpp b/src/SB/Core/x/xPad.cpp index ab40ef460..2fddb9456 100644 --- a/src/SB/Core/x/xPad.cpp +++ b/src/SB/Core/x/xPad.cpp @@ -54,6 +54,38 @@ void xPadRumbleEnable(S32 idx, S32 enable) } } +void xPadAnalogIsDigital(S32 idx, S32 enable) +{ + if (idx != 0) + return; + + _tagxPad* pad = &mPad[idx]; + + if (enable) + { + pad->flags |= 0x10; + } + else + { + pad->flags &= ~0x10; + } + + if (pad->al2d_timer >= 0.35f) + { + pad->al2d_timer = 0.35f; + } + + if (pad->ar2d_timer >= 0.35f) + { + pad->ar2d_timer = 0.35f; + } + + if (pad->d_timer >= 0.35f) + { + pad->d_timer = 0.35f; + } +} + void xPadKill() { iPadKill(); diff --git a/src/SB/Core/x/xPad.h b/src/SB/Core/x/xPad.h index aaf97dbf9..c4ef619f5 100644 --- a/src/SB/Core/x/xPad.h +++ b/src/SB/Core/x/xPad.h @@ -108,4 +108,6 @@ void xPadDestroyRumbleChain(_tagxPad* pad); void xPadDestroyRumbleChain(S32 idx); S32 xPadAddRumble(S32 idx, _tagRumbleType type, F32 time, S32 replace, U32 fxflags); +void xPadAnalogIsDigital(F32, F32); + #endif diff --git a/src/SB/Core/x/xRenderState.cpp b/src/SB/Core/x/xRenderState.cpp index 93f4fedd9..4a17ae242 100644 --- a/src/SB/Core/x/xRenderState.cpp +++ b/src/SB/Core/x/xRenderState.cpp @@ -1,6 +1,9 @@ #include "xRenderState.h" -extern int sBlendTable[11]; +static int sBlendTable[11] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; void xRenderStateSetTexture(RwTexture* texture) { diff --git a/src/SB/Core/x/xSpline.h b/src/SB/Core/x/xSpline.h index dfbe0e17e..50a103e4a 100644 --- a/src/SB/Core/x/xSpline.h +++ b/src/SB/Core/x/xSpline.h @@ -31,4 +31,7 @@ struct xSpline3 F32* arcLength; }; +void xSpline3_ArcInit(xSpline3* spl, U32 sample); +xSpline3* xSpline3_Bezier(xVec3* points, F32* time, U32 numpoints, U32 numalloc, xVec3* p1, xVec3* p2); + #endif diff --git a/src/SB/Core/x/xTimer.cpp b/src/SB/Core/x/xTimer.cpp index 7d836d57f..7383cb632 100644 --- a/src/SB/Core/x/xTimer.cpp +++ b/src/SB/Core/x/xTimer.cpp @@ -34,6 +34,22 @@ void xTimerInit(void* b, void* tasset) xTimerInit((xBase*)b, (xTimerAsset*)tasset); } +void xTimerSave(xTimer* ent, xSerial* s) +{ + xBaseSave(ent, s); + + s->Write(ent->state); + s->Write(ent->secondsLeft); +} + +void xTimerLoad(xTimer* ent, xSerial* s) +{ + xBaseLoad(ent, s); + + s->Read(&ent->state); + s->Read(&ent->secondsLeft); +} + S32 xTimer_ObjIDIsPauseTimer(U32 id) { if (id == 0xCB3F6340) return TRUE; diff --git a/src/SB/Game/zMusic.cpp b/src/SB/Game/zMusic.cpp index cddb8c58b..12122893d 100644 --- a/src/SB/Game/zMusic.cpp +++ b/src/SB/Game/zMusic.cpp @@ -114,8 +114,6 @@ void zMusicInit() volume_reset(); } -// WIP. -#ifdef NON_MATCHING // Correct, but won't work due to the switch case jump table (messes with offsets) S32 getCurrLevelMusicEnum() { @@ -183,7 +181,6 @@ S32 getCurrLevelMusicEnum() return snd_enum; } -#endif #if 0 // Probably floating point memes idk diff --git a/src/SB/Game/zNPCGoalRobo.cpp b/src/SB/Game/zNPCGoalRobo.cpp index 9eb786cdf..f627ec547 100644 --- a/src/SB/Game/zNPCGoalRobo.cpp +++ b/src/SB/Game/zNPCGoalRobo.cpp @@ -1,4 +1,5 @@ #include "xVec3.h" +#include "xMath.h" #include "xMath3.h" #include "zNPCGoalRobo.h" #include "zNPCTypeRobot.h" @@ -9,8 +10,8 @@ #include "zNPCGoalStd.h" #include "zNPCSupport.h" #include "zNPCGoals.h" - -F32 f_0 = 0.0f; // needed at file level to change scheduling for +#include "zGameExtras.h" +#include "zNPCSupport.h" xFactoryInst* GOALCreate_Robotic(S32 who, RyzMemGrow* grow, void*) { @@ -199,7 +200,7 @@ xFactoryInst* GOALCreate_Robotic(S32 who, RyzMemGrow* grow, void*) S32 zNPCGoalAlertFodder::Enter(F32 dt, void* updCtxt) { flg_attack = 0; - tmr_alertfod = f_0; // need non-const float to get scheduling right + tmr_alertfod = 0.0f; // need non-const float to get scheduling right alertfod = FODDER_ALERT_NOTICE; return zNPCGoalCommon::Enter(dt, updCtxt); } @@ -369,6 +370,21 @@ void zNPCGoalAlertFodder::GetInArena(F32 dt) npc->ThrottleApply(dt, &dir, 0); } +int zNPCGoalAttackFodder::CattleNotify::Notify(en_haznote hazNote, NPCHazard* haz) +{ + switch (hazNote) + { + case HAZ_NOTE_DISCARD: + case HAZ_NOTE_ABORT: + goal->haz_cattle = NULL; + break; + case HAZ_NOTE_HITPLAYER: + goal->flg_attack |= 3; + break; + } + return 0; +} + S32 zNPCGoalAttackFodder::Enter(F32 dt, void* updCtxt) { zNPCRobot* npc = (zNPCRobot*)this->psyche->clt_owner; @@ -480,6 +496,20 @@ void zNPCGoalAlertFodBzzt::GetInArena(F32 dt) npc->ThrottleApply(dt, &dir, 0); } +void zNPCGoalAlertFodBzzt::ToggleOrbit() +{ + if (flg_alert & 1) + { + flg_alert &= -2; + flg_alert |= 2; + } + else + { + flg_alert |= 1; + flg_alert &= -3; + } +} + void zNPCGoalAlertChomper::GetInArena(F32 dt) { zNPCRobot* npc; @@ -711,8 +741,7 @@ S32 NPCArena::IncludesPlayer(F32 rad_thresh, xVec3* vec) S32 NPCArena::IsReady() { - // TODO: not matching, not sure what this is - return this->rad_arena == 1.0f; // @1130 check this float value + return rad_arena > 1.0f; } void NPCBattle::LeaveBattle(zNPCRobot*) @@ -755,3 +784,343 @@ void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) o->y = y; o->z = z; } + +S32 zNPCGoalDogPounce::NPCMessage(NPCMsg* mail) +{ + S32 ret = 0; + switch (mail->msgid) + { + case NPC_MID_DAMAGE: + flg_user = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +S32 zNPCGoalDogPounce::Enter(F32 dt, void* updCtxt) +{ + flg_user = 0; + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalDogPounce::Exit(F32 dt, void* updCtxt) +{ + if (flg_user == 0) + { + Detonate(); + } + return zNPCGoalPushAnim::Exit(dt, updCtxt); +} + +S32 zNPCGoalDogBark::Enter(F32 dt, void* updCtxt) +{ + zNPCGoalLoopAnim::LoopCountSet(1); + return zNPCGoalLoopAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalDogDash::Enter(F32 dt, void* updCtxt) +{ + zNPCGoalLoopAnim::LoopCountSet(1); + return zNPCGoalLoopAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalAttackTarTar::Enter(F32 dt, void* updCtxt) +{ + ((zNPCCommon*)(psyche->clt_owner))->VelStop(); + flg_pushanim |= 2; + idx_launch = 1; + flg_attack = 0; + xVec3Copy(&pos_aimbase, &g_O3); + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalAttackChomper::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* com = ((zNPCCommon*)(psyche->clt_owner)); + com->VelStop(); + com->SndPlayRandom(NPC_STYP_ATTACK); + + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalEvilPat::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* com = ((zNPCCommon*)(psyche->clt_owner)); + + S32 typ = com->SelfType(); + + if ((typ - 'NT\0\0') == 'R3') + { + com->flg_vuln |= 0x80000000; + } + + GlyphStart(); + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalEvilPat::Exit(F32 dt, void* updCtxt) +{ + zNPCCommon* com = ((zNPCCommon*)(psyche->clt_owner)); + + S32 typ = com->SelfType(); + + if ((typ - 'NT\0\0') == 'R3') + { + com->flg_vuln &= 0x7FFFFFFF; + } + + *(F32*)(&com->snd_queue[6].flg_snd) = -1.0f; + + GlyphStop(); + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalEvilPat::NPCMessage(NPCMsg* mail) +{ + zNPCRobot* npc = ((zNPCRobot*)(psyche->clt_owner)); + switch (mail->msgid) + { + case NPC_MID_STUN: + F32 stuntime = mail->stundata.tym_stuntime; + F32 blah = (xurand() - 0.5f); + blah = 0.25f * blah; + *(F32*)(&npc->snd_queue[6].flg_snd) = stuntime + (stuntime * blah); + return 1; + } + return 0; +} + +S32 zNPCGoalEvilPat::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + U32 nextgoal; + + zNPCRobot* npc = ((zNPCRobot*)(psyche->clt_owner)); + + if (npc->tmr_stunned < 0.0f) + { + *trantype = GOAL_TRAN_SET; + nextgoal = 'NGR4'; + } + else + { + *trantype = GOAL_TRAN_PUSH; + nextgoal = 'NGRa'; + } + + return (*trantype != GOAL_TRAN_NONE) ? nextgoal : xGoal::Process(trantype, dt, updCtxt, scene); +} + +S32 zNPCGoalTaunt::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); + npc->SndPlayRandom(NPC_STYP_LAUGH); + zNPCGoalLoopAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalAttackArfMelee::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); + FXStreakPrep(); + npc->SndPlayRandom(NPC_STYP_PUNCH); + zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +void zNPCGoalAttackHammer::ModifyAnimSpeed() +{ + zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); + F32 speed = 1.5f; + U32 cheats = zGameExtras_CheatFlags(); + if ((cheats & 0x800)) + { + speed = 2.5f; + } + xAnimSingle* anim = npc->AnimCurSingle(); + anim->CurrentSpeed = speed; +} + +S32 zNPCGoalEvade::Enter(F32 dt, void* updCtxt) +{ + flg_evade = 0; + + if (xrand() & 0x00800000) + { + flg_evade |= 1; + } + else + { + flg_evade |= 2; + } + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalHokeyPokey::Enter(F32 dt, void* updCtxt) +{ + zNPCFodBzzt* bzzt = ((zNPCFodBzzt*)(psyche->clt_owner)); + flg_hokey = (xrand() >> 0x17) & 1; + flg_hokey |= 2; + ang_spinrate = 0.0f; + bzzt->DiscoReset(); + return zNPCGoalLoopAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalTubeBirth::Enter(F32 dt, void* updCtxt) +{ + zNPCTubeSlave* npc = ((zNPCTubeSlave*)(psyche->clt_owner)); + npc->hitpoints = npc->cfg_npc->pts_damage; + npc->VelStop(); + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAttackMonsoon::Enter(F32 dt, void* updCtxt) +{ + idx_launch = 0; + flg_pushanim |= 2; + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertArf::Enter(F32 dt, void* updCtxt) +{ + alertarf = ARF_ALERT_READY; + tmr_reload = -1.0f; + flg_user = 1; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertHammer::Enter(F32 dt, void* updCtxt) +{ + flg_attack = 0; + alertham = HAMMER_ALERT_NOTICE; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertChuck::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); + alertchuk = CHUCK_ALERT_NOTICE; + npc->VelStop(); + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertChomper::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); + alertchomp = CHOMPER_ALERT_NOTICE; + npc->VelStop(); + pos_evade = g_O3; + tmr_evade = -1.0f; + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalTubeLasso::Enter(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); + npc->VelStop(); + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertSlick::Resume(F32 dt, void* updCtxt) +{ + zNPCCommon* npc = ((zNPCCommon*)(psyche->clt_owner)); + npc->VelStop(); + flg_info |= 2; + return zNPCGoalCommon::Resume(dt, updCtxt); +} + +S32 zNPCGoalAlertTubelet::Enter(F32 dt, void* updCtxt) +{ + zNPCTubeSlave* npc = ((zNPCTubeSlave*)(psyche->clt_owner)); + npc->tubespot = ROBO_TUBE_MARY; + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalAlertTubelet::Exit(F32 dt, void* updCtxt) +{ + zNPCTubelet* npc = ((zNPCTubelet*)(psyche->clt_owner)); + zNPC_SNDStop(eNPCSnd_TubeAttack); + npc->pete_attack_last = 0; + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalAlertTubelet::Resume(F32 dt, void* updCtxt) +{ + zNPCTubelet* npc = ((zNPCTubelet*)(psyche->clt_owner)); + npc->tubestat = TUBE_STAT_ATTACK; + return zNPCGoalCommon::Resume(dt, updCtxt); +} + +S32 zNPCGoalAlertPuppy::Resume(F32 dt, void* updCtxt) +{ + zNPCChomper* npc = ((zNPCChomper*)(psyche->clt_owner)); + flg_info |= 2; + return zNPCGoalCommon::Resume(dt, updCtxt); +} + +S32 zNPCGoalAlertChuck::Resume(F32 dt, void* updCtxt) +{ + zNPCChuck* npc = ((zNPCChuck*)(psyche->clt_owner)); + flg_info |= 2; + return zNPCGoalCommon::Resume(dt, updCtxt); +} + +S32 zNPCGoalAlertMonsoon::Resume(F32 dt, void* updCtxt) +{ + alertmony = MONSOON_ALERT_BEGIN; + flg_attack = 0; + return zNPCGoalCommon::Resume(dt, updCtxt); +} + +S32 zNPCGoalAlertFodBomb::Resume(F32 dt, void* updCtxt) +{ + flg_info |= 2; + return zNPCGoalCommon::Resume(dt, updCtxt); +} + +S32 zNPCGoalAttackArfMelee::Exit(F32 dt, void* updCtxt) +{ + FXStreakDone(); + return zNPCGoalPushAnim::Exit(dt, updCtxt); +} + +void zNPCGoalAttackArfMelee::FXStreakDone() +{ + for (S32 i = 0; i < (S32)(sizeof(this->streakID) / sizeof(U32)); i++) + { + xFXStreakStop(streakID[i]); + streakID[i] = 0xDEAD; + } +} + +void zNPCGoalTubeAttack::AttackDataReset() +{ + zNPCTubelet* npc = ((zNPCTubelet*)(psyche->clt_owner)); + flg_attack = 0; + if (npc->tubestat == TUBE_STAT_ATTACK) + { + mary.marystat = TUBE_MARY_WAIT; + mary.ang_spinrate = 0.0; + } + else + { + paul.flg_paul = 1; + paul.cnt_nextlos = -1; + paul.len_laser = 10.0f; + } +} + +S32 zNPCGoalWound::NPCMessage(NPCMsg* msg) +{ + switch (msg->msgid) + { + case NPC_MID_DAMAGE: + return 1; + } + return 0; +} \ No newline at end of file diff --git a/src/SB/Game/zNPCGoalStd.h b/src/SB/Game/zNPCGoalStd.h index 8a577a624..b34ec27ce 100644 --- a/src/SB/Game/zNPCGoalStd.h +++ b/src/SB/Game/zNPCGoalStd.h @@ -312,6 +312,11 @@ class zNPCGoalAttackArfMelee : public zNPCGoalPushAnim // total size: 0x64 public: zNPCGoalAttackArfMelee(S32); + S32 Enter(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); + S32 FXStreakPrep(); + void FXStreakDone(); + U32 streakID[4]; // offset 0x54, size 0x10 }; @@ -385,6 +390,12 @@ class zNPCGoalEvilPat : public zNPCGoalCommon // total size: 0x4C public: zNPCGoalEvilPat(S32); + S32 Enter(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); + F32 GlyphStart(); + F32 GlyphStop(); + S32 NPCMessage(NPCMsg* mail); + S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); }; class zNPCGoalPatCarry : public zNPCGoalCommon @@ -399,12 +410,14 @@ class zNPCGoalStunned : public zNPCGoalCommon // total size: 0x4C public: zNPCGoalStunned(S32); + S32 Enter(F32 dt, void* updCtxt); }; class zNPCGoalEvade : public zNPCGoalCommon { public: zNPCGoalEvade(S32); + S32 Enter(F32 dt, void* updCtxt); S32 flg_evade; // offset 0x4C, size 0x4 }; @@ -437,6 +450,7 @@ class zNPCGoalAlertArf : public zNPCGoalCommon // total size: 0x54 public: zNPCGoalAlertArf(S32); + S32 Enter(F32 dt, void* updCtxt); en_alertarf alertarf; // offset 0x4C, size 0x4 F32 tmr_reload; // offset 0x50, size 0x4 }; @@ -456,6 +470,7 @@ class zNPCGoalAlertPuppy : public zNPCGoalCommon // total size: 0x50 public: zNPCGoalAlertPuppy(S32); + S32 Resume(F32 dt, void* updCtxt); enum en_alertpuppy alertpup; // offset 0x4C, size 0x4 }; @@ -536,6 +551,9 @@ class zNPCGoalAlertTubelet : public zNPCGoalCommon // total size: 0x5C public: zNPCGoalAlertTubelet(S32); + S32 Exit(F32 dt, void* updCtxt); + S32 Enter(F32 dt, void* updCtxt); + S32 Resume(F32 dt, void* updCtxt); S32 flg_attack; // offset 0x4C, size 0x4 S32 cnt_nextlos; // offset 0x50, size 0x4 F32 len_laser; // offset 0x54, size 0x4 @@ -565,6 +583,7 @@ class zNPCGoalAlertMonsoon : public zNPCGoalCommon // total size: 0x70 public: zNPCGoalAlertMonsoon(S32); + S32 Resume(F32 dt, void* updCtxt); xVec3 dir_attack; // offset 0x4C, size 0xC S32 flg_attack; // offset 0x58, size 0x4 en_alertmony alertmony; // offset 0x5C, size 0x4 @@ -624,6 +643,7 @@ class zNPCGoalAlertHammer : public zNPCGoalCommon // total size: 0x58 public: zNPCGoalAlertHammer(S32); + S32 Enter(F32 dt, void* updCtxt); S32 flg_attack; // offset 0x4C, size 0x4 en_alertham alertham; // offset 0x50, size 0x4 F32 tmr_alertham; // offset 0x54, size 0x4 @@ -651,23 +671,17 @@ struct zNPCGoalAlertFodBzzt : zNPCGoalCommon S32 Exit(); S32 Enter(F32 dt, void* updCtxt); void GetInArena(F32 dt); + void ToggleOrbit(); }; struct zNPCGoalAttackFodder; -struct CattleNotify : HAZNotify -{ - zNPCGoalAttackFodder* goal; - - CattleNotify(S32 myType); - S32 Notify(en_haznote note); -}; - class zNPCGoalAttackMonsoon : public zNPCGoalPushAnim { // total size: 0x58 public: zNPCGoalAttackMonsoon(S32); + S32 Enter(F32 dt, void* updCtxt); S32 idx_launch; // offset 0x54, size 0x4 }; @@ -676,6 +690,7 @@ class zNPCGoalAttackTarTar : public zNPCGoalPushAnim // total size: 0x68 public: zNPCGoalAttackTarTar(S32); + S32 Enter(F32 dt, void* updCtxt); S32 flg_attack; // offset 0x54, size 0x4 S32 idx_launch; // offset 0x58, size 0x4 xVec3 pos_aimbase; // offset 0x5C, size 0xC @@ -686,20 +701,31 @@ class zNPCGoalAttackHammer : public zNPCGoalPushAnim // total size: 0x78 public: zNPCGoalAttackHammer(S32); + void ModifyAnimSpeed(); S32 flg_attack; // offset 0x54, size 0x4 xVec3 pos_lastVert; // offset 0x58, size 0xC xVec3 pos_oldVert; // offset 0x64, size 0xC U32 streakID[2]; // offset 0x70, size 0x8 }; + class zNPCGoalAttackChomper : public zNPCGoalPushAnim { // total size: 0x54 public: zNPCGoalAttackChomper(S32); + S32 Enter(F32 dt, void* updCtxt); }; struct zNPCGoalAttackFodder : zNPCGoalPushAnim { + struct CattleNotify : HAZNotify + { + zNPCGoalAttackFodder* goal; + + CattleNotify(S32 myType); + S32 Notify(en_haznote note, NPCHazard*); + }; + xVec3 dir_attack; S32 flg_attack; CattleNotify cbNotify; @@ -725,6 +751,7 @@ class zNPCGoalAlertFodBomb : public zNPCGoalCommon // total size: 0x5C public: zNPCGoalAlertFodBomb(S32); + S32 Resume(F32 dt, void* updCtxt); S32 flg_attack; // offset 0x4C, size 0x4 en_alertbomb alertbomb; // offset 0x50, size 0x4 F32 tmr_nextping; // offset 0x54, size 0x4 @@ -771,6 +798,8 @@ class zNPCGoalDogBark : public zNPCGoalLoopAnim // total size: 0x6C public: zNPCGoalDogBark(S32); + + S32 Enter(F32 dt, void* updCtxt); }; class zNPCGoalDamage : public zNPCGoalCommon @@ -817,6 +846,7 @@ class zNPCGoalTubeLasso : public zNPCGoalCommon // total size: 0x4C public: zNPCGoalTubeLasso(S32); + S32 Enter(F32 dt, void* updCtxt); }; class zNPCGoalTubeDead : public zNPCGoalDead @@ -853,6 +883,7 @@ class zNPCGoalTubeBirth : public zNPCGoalCommon { public: zNPCGoalTubeBirth(S32); + S32 Enter(F32 dt, void* updCtxt); // total size: 0x4C }; @@ -861,6 +892,7 @@ class zNPCGoalTubeAttack : public zNPCGoalCommon // total size: 0x84 public: zNPCGoalTubeAttack(S32); + void AttackDataReset(); S32 flg_attack; // offset 0x4C, size 0x4 union { @@ -931,7 +963,12 @@ class zNPCGoalKnock : public zNPCGoalCommon { // total size: 0x64 public: - zNPCGoalKnock(S32); + zNPCGoalKnock(S32 id) : zNPCGoalCommon(id) + { + SetFlags(2); + flg_npcgable |= 1; + } + S32 flg_knock; // offset 0x4C, size 0x4 xVec3 pos_bumper; // offset 0x50, size 0xC S32 floorBounce; // offset 0x5C, size 0x4 @@ -943,6 +980,7 @@ class zNPCGoalWound : public zNPCGoalPushAnim // total size: 0x64 public: zNPCGoalWound(S32); + S32 NPCMessage(NPCMsg*); xVec3 dir_fling; // offset 0x54, size 0xC S32 flg_knock; // offset 0x60, size 0x4 }; @@ -952,6 +990,7 @@ class zNPCGoalHokeyPokey : public zNPCGoalLoopAnim // total size: 0x74 public: zNPCGoalHokeyPokey(S32); + S32 Enter(F32 dt, void* updCtxt); S32 flg_hokey; // offset 0x6C, size 0x4 F32 ang_spinrate; // offset 0x70, size 0x4 }; @@ -969,6 +1008,10 @@ class zNPCGoalDogPounce : public zNPCGoalPushAnim // total size: 0x54 public: zNPCGoalDogPounce(S32); + S32 NPCMessage(NPCMsg* mail); + S32 Enter(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); + void Detonate(); }; class zNPCGoalDogDash : public zNPCGoalLoopAnim @@ -976,6 +1019,7 @@ class zNPCGoalDogDash : public zNPCGoalLoopAnim // total size: 0x6C public: zNPCGoalDogDash(S32); + S32 Enter(F32 dt, void* updCtxt); }; xFactoryInst* GOALCreate_Standard(S32 who, RyzMemGrow* grow, void*); diff --git a/src/SB/Game/zNPCGoalVillager.cpp b/src/SB/Game/zNPCGoalVillager.cpp index 558834ea5..c156b83cb 100644 --- a/src/SB/Game/zNPCGoalVillager.cpp +++ b/src/SB/Game/zNPCGoalVillager.cpp @@ -531,15 +531,19 @@ S32 zNPCGoalBoyWeep::Enter(F32 dt, void* updCtxt) 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) + switch (mail->msgid) { - ang_spinrate += 16.0f; - zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; - npc->SndPlayRandom(NPC_STYP_EXCLAIM); + case NPC_MID_DAMAGE: + if (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); + } + break; } + return 0; } diff --git a/src/SB/Game/zNPCSupport.h b/src/SB/Game/zNPCSupport.h index 8ccb5fe2c..c103db454 100644 --- a/src/SB/Game/zNPCSupport.h +++ b/src/SB/Game/zNPCSupport.h @@ -15,6 +15,16 @@ enum en_npctgt NPC_TGT_FORCEINT = 0x7fffffff }; +enum _tageNPCSnd +{ + eNPCSnd_GloveAttack, + eNPCSnd_SleepyAttack, + eNPCSnd_TubeAttack, + eNPCSnd_FodBzztAttack, + eNPCSnd_JellyfishAttack, + eNPCSnd_Total +}; + struct NPCTarget { en_npctgt typ_target; @@ -48,5 +58,6 @@ xVec3* NPCC_faceDir(xEnt* ent); void NPCC_ang_toXZDir(F32 angle, xVec3* dir); F32 NPCC_aimVary(xVec3* dir_aim, xVec3* pos_src, xVec3* pos_tgt, F32 dst_vary, S32 flg_vary, xVec3* pos_aimPoint); F32 NPCC_ds2_toCam(const xVec3* pos_from, xVec3* delta); +void zNPC_SNDStop(_tageNPCSnd snd); #endif diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 6060af24d..d467db8e2 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -410,6 +410,7 @@ struct zNPCCommon : xNPCBasic S32 AnimStart(U32 animID, S32 forceRestart); xAnimState* AnimFindState(U32 animID); xAnimState* AnimCurState(); + xAnimSingle* AnimCurSingle(); U32 AnimCurStateID(); void GiveReward(); S32 SndPlayFromSFX(xSFX* sfx, U32* sid_played); diff --git a/src/SB/Game/zNPCTypeRobot.h b/src/SB/Game/zNPCTypeRobot.h index 4e99ddd26..7ae2e05a7 100644 --- a/src/SB/Game/zNPCTypeRobot.h +++ b/src/SB/Game/zNPCTypeRobot.h @@ -178,6 +178,7 @@ struct zNPCFodBzzt : zNPCRobot zNPCFodBzzt(S32 myType); zNPCLassoInfo* PRIV_GetLassoData(); + void DiscoReset(); }; struct zNPCChomper : zNPCRobot