From 18caa26cd65d1605ce275d5f32211c820ecd6a48 Mon Sep 17 00:00:00 2001 From: Magi Date: Tue, 8 Sep 2026 01:33:02 +0200 Subject: [PATCH 1/4] feat: TBW started, shakeCamera done --- .DS_Store | Bin 0 -> 6148 bytes include/Enemy/BossWanwan.hpp | 54 ++++++++++++++++++++++++++++++ orig/.DS_Store | Bin 0 -> 8196 bytes src/Enemy/bosswanwan.cpp | 62 +++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 .DS_Store create mode 100644 orig/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2c79ff16de1b73df29ec1ac92378e3982085ea43 GIT binary patch literal 6148 zcmeH~L2AQ53`M_EF9O+k+2w3Ot|5K^XdM5Jxl_ literal 0 HcmV?d00001 diff --git a/include/Enemy/BossWanwan.hpp b/include/Enemy/BossWanwan.hpp index 7bd1f1d4b..dc434f66b 100644 --- a/include/Enemy/BossWanwan.hpp +++ b/include/Enemy/BossWanwan.hpp @@ -2,8 +2,62 @@ #define ENEMY_BOSS_WANWAN_HPP #include +#include +#include +#include +#include class TLiveActor; +class TBossWanwan; + +class TBWParams : public TSpineEnemyParams { +public: + /* * TSpineEnemyParams ends at 0xA8. * + * Every TParamRT occupies 0x14 bytes: + * * +0x00 : TParam / base data + * * +0x04 : ... + * * +0x0C : ... + * * +0x10 : actual parameter value + * * * Therefore: * parameter start = X * parameter value = X + 0x10 */ + TBWParams(const char*); + + /* 0x0A8 */ TParamRT mSLMarchSpeed; + /* 0x0BC */ TParamRT mSLTurnSpeed; + /* 0x0D0 */ TParamRT mSLLeashNodeLen; + /* 0x0E4 */ TParamRT mSLPicketHeight; + /* 0x0F8 */ TParamRT mSLPicketRadius; + /* 0x10C */ TParamRT mSLChainHitHeight; + /* 0x120 */ TParamRT mSLChainHitRadius; + /* 0x134 */ TParamRT mSLChainGroundRadius; + /* 0x148 */ TParamRT mSLPullLimit; + /* 0x15C */ TParamRT mSLAttackSpeed; + /* 0x170 */ TParamRT mSLStunTimer; + /* 0x184 */ TParamRT mSLSearchLength; + /* 0x198 */ TParamRT mSLSearchAngle; + /* 0x1AC */ TParamRT mSLBWHitPointMax; + /* 0x1C0 */ TParamRT mSLHeadGap; + /* 0x1D4 */ TParamRT mSLShakeLengthMax; + /* 0x1E8 */ TParamRT mSLShakeLengthMaxHP0; +}; + +class TBossWanwan : public TSpineEnemy { +public: + TBossWanwan(const char* name = "ボスワンワン"); + + virtual void kill(); + virtual void init(TLiveManager*); + virtual void shakeCamera(int shakeType); +}; + +class TBossWanwanManager : public TEnemyManager { +public: + TBossWanwanManager(const char* name = "ボスワンワンマネージャ"); + + virtual void load(JSUMemoryInputStream&); + + TSpineEnemy* createEnemyInstance(); + void createModelData(); +}; DECLARE_NERVE(TNerveBWGraphWander, TLiveActor); DECLARE_NERVE(TNerveBWRoll, TLiveActor); diff --git a/orig/.DS_Store b/orig/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a4b0a3e00c4ec61ffad68a74c515a4346dc0201b GIT binary patch literal 8196 zcmeHMTWl0n7(U-=DKp~0wB=G@fT0xxp|V9#xtVRZAT5_xTI{w(+P#c0GMy{Z)I_5(czKd|OZw#9m}t=GgBpWXV|?)z6XS!4MtuR}f9A|Kz1TNmFw9BL`Q}{y z|IB{p|IXR7%NRpbA=|)M4P#89EKr|C#lIxcFY=Vc!A$ z8R8P7GGZWNU@8OR?q0!eW_wr%YaM@o7do5J;rPWw+VRqim8H{zj_v1Tv2Vc3%4bx} zRMabGU8&7BlHJLk-UC{nURAWMp|-)i?YaJ~R?a8v)93hyy`h$j=eFl8(chKvoWg+X z_vw|Hl#?kqsl3(bI34zJ%kN1Y>$HyL#j`NX`vyV>q_?cUM`;q{3dOh zN;=RBzO~OH|8~)8rdj;ClbC=yGN;B|vHIHUZrs+mqjm4TQN6ONdhR?;>#?(zo40Sb zt=#@0JDWe;o$@o5o3-6TT}9is(~i~YrUtA^tX0*~g^L#J#u8&$scW){qSqs3Y|vxW8mkngSF|T`7L~GDTVvF#dP?c^i5ux6 zrma_XU+p|%yP@eu?FL29s{5T(+H$0~&DvH)-=%gH<#Nczd0JdilNoPdfIg%z+Y-ih zMgK@SC??*W^7CzjmRowIgwdiXJ^tZT&T1QStz5}skD>(YOYOpBd)Cf-Imt$?af_mK z3ulelEcwwFEne8sX&8OFZo5T0Pm4m!L{RYcbBdzW#jlZzQ&(D}x_2}E!E-=#T|6c` zR5~)2u?=ho+so2yfSqIyu+!`e8)5IUbL?~WJ^O|I$#l@fdI5TX-|?;@!N5_wobW;w~TJC-{BxBk=Gv zV+UouRPy`jX|nnTrTX|g)2Pqf*|M{B*Y5wN`o5kc^)`P&&GMCNVjDNz)HD{AGKfoY zJ6;cg1SSY4kU$V7lf##kX)IZ)nfpm2*0IUDEa_FBDRiue$Te!~G*h2JDw5T!S5dWs z6eO!_>rGSVBwSf-SZ`{28Obu(1B~nIsfw_&d5fm$-mLU(Wb#XjUEQSIPgx`}ZdhVqLPfCg69(6D!m&RL>Di>A!X_T#utaL1 T^q>C_5S{ +#include +#include +#include +#include +#include +#include +#include +#include +void TBossWanwan::kill() { return; } +void TBossWanwan::shakeCamera(int shakeType) +{ + if (!SMS_IsMarioTouchGround4cm()) { + return; + } + + f32 dist = this->mDistToMarioSquared; + + if (0.0f < dist) { + // TODO: This is a bit tricky. There's still some problems here + f64 r = __frsqrte(dist); + dist = dist * (0.5 * r * -(dist * (r * r) - 3.0)); + } + + TBWParams* params = (TBWParams*)this->getSaveParam(); + f32 shakeLengthMax = params->mSLShakeLengthMax.get(); + + TBWParams* params2 = (TBWParams*)this->getSaveParam(); + f32 shakeLengthMaxHP0 = params2->mSLShakeLengthMaxHP0.get(); + + f32 ratio = 1.0; + if (this->mMActor->checkCurBckFromIndex(0) == 0) { + TBWParams* params3 = (TBWParams*)this->getSaveParam(); + ratio = (f32)this->mHitPoints / (f32)params3->mSLBWHitPointMax.get(); + } + + f32 effectiveDist + = shakeLengthMax * ratio + shakeLengthMaxHP0 * (1.0f - ratio); + + f32 delta = effectiveDist - dist; + + if (delta < 0.0f) { + return; + } + + f32 power = delta / effectiveDist; + if (1.0f < power) { + power = 1.0f; + } + + power *= ratio; + + gpCameraShake->startShake((EnumCamShakeMode)shakeType, power); + SMSRumbleMgr->start(8, &this->mPosition); +} + +TSpineEnemy* TBossWanwanManager::createEnemyInstance() +{ + return new TBossWanwan(); +} + +void TBossWanwanManager::createModelData() { } From 1a02973cb4ee82a5e8ab29071f9655f98d5cde4e Mon Sep 17 00:00:00 2001 From: Magi Date: Tue, 8 Sep 2026 01:35:04 +0200 Subject: [PATCH 2/4] feat: progress TBW, first started shakeCamera --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 3 +++ orig/.DS_Store | Bin 8196 -> 0 bytes 3 files changed, 3 insertions(+) delete mode 100644 .DS_Store delete mode 100644 orig/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 2c79ff16de1b73df29ec1ac92378e3982085ea43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~L2AQ53`M_EF9O+k+2w3Ot|5K^XdM5Jxl_ diff --git a/.gitignore b/.gitignore index 9bc17b380..460106770 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ compile_commands.json /*.txt *.exe tools/mwcc_compiler + +# Apple +.DS_Store diff --git a/orig/.DS_Store b/orig/.DS_Store deleted file mode 100644 index a4b0a3e00c4ec61ffad68a74c515a4346dc0201b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHMTWl0n7(U-=DKp~0wB=G@fT0xxp|V9#xtVRZAT5_xTI{w(+P#c0GMy{Z)I_5(czKd|OZw#9m}t=GgBpWXV|?)z6XS!4MtuR}f9A|Kz1TNmFw9BL`Q}{y z|IB{p|IXR7%NRpbA=|)M4P#89EKr|C#lIxcFY=Vc!A$ z8R8P7GGZWNU@8OR?q0!eW_wr%YaM@o7do5J;rPWw+VRqim8H{zj_v1Tv2Vc3%4bx} zRMabGU8&7BlHJLk-UC{nURAWMp|-)i?YaJ~R?a8v)93hyy`h$j=eFl8(chKvoWg+X z_vw|Hl#?kqsl3(bI34zJ%kN1Y>$HyL#j`NX`vyV>q_?cUM`;q{3dOh zN;=RBzO~OH|8~)8rdj;ClbC=yGN;B|vHIHUZrs+mqjm4TQN6ONdhR?;>#?(zo40Sb zt=#@0JDWe;o$@o5o3-6TT}9is(~i~YrUtA^tX0*~g^L#J#u8&$scW){qSqs3Y|vxW8mkngSF|T`7L~GDTVvF#dP?c^i5ux6 zrma_XU+p|%yP@eu?FL29s{5T(+H$0~&DvH)-=%gH<#Nczd0JdilNoPdfIg%z+Y-ih zMgK@SC??*W^7CzjmRowIgwdiXJ^tZT&T1QStz5}skD>(YOYOpBd)Cf-Imt$?af_mK z3ulelEcwwFEne8sX&8OFZo5T0Pm4m!L{RYcbBdzW#jlZzQ&(D}x_2}E!E-=#T|6c` zR5~)2u?=ho+so2yfSqIyu+!`e8)5IUbL?~WJ^O|I$#l@fdI5TX-|?;@!N5_wobW;w~TJC-{BxBk=Gv zV+UouRPy`jX|nnTrTX|g)2Pqf*|M{B*Y5wN`o5kc^)`P&&GMCNVjDNz)HD{AGKfoY zJ6;cg1SSY4kU$V7lf##kX)IZ)nfpm2*0IUDEa_FBDRiue$Te!~G*h2JDw5T!S5dWs z6eO!_>rGSVBwSf-SZ`{28Obu(1B~nIsfw_&d5fm$-mLU(Wb#XjUEQSIPgx`}ZdhVqLPfCg69(6D!m&RL>Di>A!X_T#utaL1 T^q>C_5S{ Date: Tue, 8 Sep 2026 16:03:52 +0200 Subject: [PATCH 3/4] feat: TBossWanwaReceiveMessage, 92% --- include/Enemy/BossWanwan.hpp | 51 ++++++++++++++++++++++++ src/Enemy/bosswanwan.cpp | 76 ++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/include/Enemy/BossWanwan.hpp b/include/Enemy/BossWanwan.hpp index dc434f66b..8dfd6621c 100644 --- a/include/Enemy/BossWanwan.hpp +++ b/include/Enemy/BossWanwan.hpp @@ -4,12 +4,54 @@ #include #include #include +#include #include #include class TLiveActor; class TBossWanwan; +class TBWHit : public THitActor { +public: + TBWHit(TBossWanwan* owner, int joint_index, + const char* name = "idk"); // yeah + + virtual void perform(u32 cue, JDrama::TGraphics* graphics); + virtual BOOL receiveMessage(THitActor* sender, u32 message); + +private: + TBossWanwan* mOwner; + u32 mJointIndex; +}; + +class TBWPicket : public THitActor { +public: + virtual void perform(u32 cue, JDrama::TGraphics* graphics); + virtual BOOL receiveMessage(THitActor* sender, u32 message); +}; + +class TBWBinder : public TBinder { +public: + TBWBinder(); + virtual void bind(TLiveActor*); +}; + +class TBWLeash : public THitActor { +public: + TBWLeash(int, const char*); + + virtual void perform(u32 cue, JDrama::TGraphics* graphics); +}; + +class TBWLeashNode : public THitActor { +public: + TBWLeashNode(int, const char*); + + virtual void perform(u32 cue, JDrama::TGraphics* graphics); + virtual void calcMatrix(); + virtual void calcTemperature(); +}; + class TBWParams : public TSpineEnemyParams { public: /* * TSpineEnemyParams ends at 0xA8. * @@ -40,13 +82,22 @@ class TBWParams : public TSpineEnemyParams { /* 0x1E8 */ TParamRT mSLShakeLengthMaxHP0; }; +// TBossWanwan size: 0x1b8 class TBossWanwan : public TSpineEnemy { public: TBossWanwan(const char* name = "ボスワンワン"); virtual void kill(); virtual void init(TLiveManager*); + BOOL receiveMessage(THitActor* sender, u32 message); virtual void shakeCamera(int shakeType); + +private: + /* 0x1A0 */ BOOL unk0; + /* 0x1A8 */ u32 mWaterHitCount; + /* 0x1AC */ u32 mDistToMarioSquared; + /* 0x1B0 */ TBWParams* mParams; + /* 0x18C */ u8 msInvincible; }; class TBossWanwanManager : public TEnemyManager { diff --git a/src/Enemy/bosswanwan.cpp b/src/Enemy/bosswanwan.cpp index dfd116080..03f254d5c 100644 --- a/src/Enemy/bosswanwan.cpp +++ b/src/Enemy/bosswanwan.cpp @@ -1,14 +1,90 @@ #include #include +#include +#include +#include #include #include #include #include +#include +#include #include #include #include +#include +#include +#include +#include +#include +#include void TBossWanwan::kill() { return; } + +BOOL TBossWanwan::receiveMessage(THitActor* sender, u32 message) +{ + u32 actorType = sender->getActorType(); + if (actorType == 0x80000001) { + return false; + } else if (actorType == 0x1000001) { + // fabricated + if (!this->msInvincible) { + gpMarioParticleManager->emit(0xE7, &sender->mPosition, 0, 0); + if (this->mHitPoints == 0) { + if (true) { + if (gpMSound->gateCheck(0x28d1)) { + MSoundSESystem::MSoundSE::startSoundActor( + 0x28d1, &this->mPosition, 0, nullptr, 0, 4); + } + } + } else if (this->mHitPoints == 1) { + MtxPtr iVar3 = this->getModel()->getAnmMtx(1); + gpMarioParticleManager->emitAndBindToMtxPtr( + 0xb0, (iVar3 + 0x58) + 0x30, 0, 0); + if (gpMSound->gateCheck(0x28c5)) { + MSoundSESystem::MSoundSE::startSoundActor( + 0x28c5, &this->mPosition, 0, nullptr, 0, 4); + } + + } else { + if (gpMSound->gateCheck(0x28be)) { + MSoundSESystem::MSoundSE::startSoundActor( + 0x28be, &this->mPosition, 0, nullptr, 0, 4); + } + } + + if (this->mHitPoints != 0) { + this->mHitPoints--; + } + + this->mWaterHitCount++; + return true; + } else { + return true; + } + + } else { + if (actorType == 0x4000005a) { + sender->receiveMessage(this, HIT_MESSAGE_HIP_DROP); + this->mHitPoints = 0; + this->mWaterHitCount++; + if (!this->unk0) { + this->unk0 = true; + } + + MtxPtr mtx = this->getModel()->getAnmMtx(1); // fabricated index + gpMarioParticleManager->emitAndBindToMtxPtr(0xB0, mtx, 0, nullptr); + + if (gpMSound->gateCheck(0x28c5)) { + MSoundSESystem::MSoundSE::startSoundActor( + 0x28c5, &this->mPosition, 0, nullptr, 0, 4); + } + } + } + + return TSpineEnemy::receiveMessage(sender, message); +} + void TBossWanwan::shakeCamera(int shakeType) { if (!SMS_IsMarioTouchGround4cm()) { From 75260e4df572f2148dc25e2a3456b4173cf4ed44 Mon Sep 17 00:00:00 2001 From: Magi Date: Wed, 9 Sep 2026 15:11:55 +0200 Subject: [PATCH 4/4] fix: misc... - fixed to SMSGetSound instead of other API - used Particles.hpp enum and created a new one based off modders tables - used msSqrtf instead of fabricated match --- include/System/Particles.hpp | 1 + src/Enemy/bosswanwan.cpp | 43 ++++++++++++++---------------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/include/System/Particles.hpp b/include/System/Particles.hpp index 9629ff185..c7ee07aac 100644 --- a/include/System/Particles.hpp +++ b/include/System/Particles.hpp @@ -144,6 +144,7 @@ enum E_SMS_EFFECT_ONETIME_NORMAL /* 0 */ { PARTICLE_MS_POPO_BOMB_B = 0xA2, GATEKEEPER_JPA_MS_GKPA_DEAD = 0xA7, GATEKEEPER_JPA_MS_GKPA_DEADSMOKE = 0xA8, + BWAN_JPA_MS_DOWNYUGE = 0xB0, PARTICLE_MS_SMB_AP_ROCK = 0xB6, PARTICLE_MS_SMB_AP_SMOKE = 0xB7, PARTICLE_MS_GESO_OSENHIT_A = 0xBC, diff --git a/src/Enemy/bosswanwan.cpp b/src/Enemy/bosswanwan.cpp index 03f254d5c..e9514c1f7 100644 --- a/src/Enemy/bosswanwan.cpp +++ b/src/Enemy/bosswanwan.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include void TBossWanwan::kill() { return; } @@ -29,28 +31,22 @@ BOOL TBossWanwan::receiveMessage(THitActor* sender, u32 message) } else if (actorType == 0x1000001) { // fabricated if (!this->msInvincible) { - gpMarioParticleManager->emit(0xE7, &sender->mPosition, 0, 0); + gpMarioParticleManager->emit(PARTICLE_MS_ENM_WATHIT, + &sender->mPosition, 0, 0); if (this->mHitPoints == 0) { - if (true) { - if (gpMSound->gateCheck(0x28d1)) { - MSoundSESystem::MSoundSE::startSoundActor( - 0x28d1, &this->mPosition, 0, nullptr, 0, 4); - } - } + + SMSGetMSound()->startSoundActor(0x28d1, &this->mPosition, 0, + nullptr, 0, 4); } else if (this->mHitPoints == 1) { MtxPtr iVar3 = this->getModel()->getAnmMtx(1); gpMarioParticleManager->emitAndBindToMtxPtr( 0xb0, (iVar3 + 0x58) + 0x30, 0, 0); - if (gpMSound->gateCheck(0x28c5)) { - MSoundSESystem::MSoundSE::startSoundActor( - 0x28c5, &this->mPosition, 0, nullptr, 0, 4); - } + SMSGetMSound()->startSoundActor(0x28c5, &this->mPosition, 0, + nullptr, 0, 4); } else { - if (gpMSound->gateCheck(0x28be)) { - MSoundSESystem::MSoundSE::startSoundActor( - 0x28be, &this->mPosition, 0, nullptr, 0, 4); - } + SMSGetMSound()->startSoundActor(0x28be, &this->mPosition, 0, + nullptr, 0, 4); } if (this->mHitPoints != 0) { @@ -72,13 +68,12 @@ BOOL TBossWanwan::receiveMessage(THitActor* sender, u32 message) this->unk0 = true; } - MtxPtr mtx = this->getModel()->getAnmMtx(1); // fabricated index - gpMarioParticleManager->emitAndBindToMtxPtr(0xB0, mtx, 0, nullptr); + MtxPtr mtx = this->getModel()->getAnmMtx(1); + gpMarioParticleManager->emitAndBindToMtxPtr(BWAN_JPA_MS_DOWNYUGE, + mtx, 0, nullptr); - if (gpMSound->gateCheck(0x28c5)) { - MSoundSESystem::MSoundSE::startSoundActor( - 0x28c5, &this->mPosition, 0, nullptr, 0, 4); - } + SMSGetMSound()->startSoundActor(0x28c5, &this->mPosition, 0, + nullptr, 0, 4); } } @@ -93,11 +88,7 @@ void TBossWanwan::shakeCamera(int shakeType) f32 dist = this->mDistToMarioSquared; - if (0.0f < dist) { - // TODO: This is a bit tricky. There's still some problems here - f64 r = __frsqrte(dist); - dist = dist * (0.5 * r * -(dist * (r * r) - 3.0)); - } + dist = MsSqrtf(dist); TBWParams* params = (TBWParams*)this->getSaveParam(); f32 shakeLengthMax = params->mSLShakeLengthMax.get();