From 2a9c9ad13af4b52a0a49b25ded4bbbfb699a390b Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Thu, 19 Mar 2026 18:49:36 +0100 Subject: [PATCH 01/16] add individual TRotation3::setDir inlines --- .../include/JSystem/JGeometry/TMatrix.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libs/JSystem/include/JSystem/JGeometry/TMatrix.hpp b/libs/JSystem/include/JSystem/JGeometry/TMatrix.hpp index 661cc72a2..8f5c3dae1 100644 --- a/libs/JSystem/include/JSystem/JGeometry/TMatrix.hpp +++ b/libs/JSystem/include/JSystem/JGeometry/TMatrix.hpp @@ -250,6 +250,25 @@ namespace JGeometry { } void setXDir(const TVec3f& rSrc); void setXDir(f32 x, f32 y, f32 z); + + inline void setXDirInline(const TVec3f& rSrc) { + this->mMtx[0][0] = rSrc.x; + this->mMtx[1][0] = rSrc.y; + this->mMtx[2][0] = rSrc.z; + } + + inline void setYDirInline(const TVec3f& rSrc) { + this->mMtx[0][1] = rSrc.x; + this->mMtx[1][1] = rSrc.y; + this->mMtx[2][1] = rSrc.z; + } + + inline void setZDirInline(const TVec3f& rSrc) { + this->mMtx[0][2] = rSrc.x; + this->mMtx[1][2] = rSrc.y; + this->mMtx[2][2] = rSrc.z; + } + void setYDir(const TVec3f& rSrc); void setYDir(f32 x, f32 y, f32 z); void setZDir(const TVec3f& rSrc); From f325a11efc4ca1430061fdde2f86f0717112bc2f Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Thu, 19 Mar 2026 18:50:08 +0100 Subject: [PATCH 02/16] Mogucchi at 49% --- include/Game/Enemy/Mogucchi.hpp | 40 ++++- include/Game/Enemy/MogucchiHill.hpp | 40 +++++ src/Game/Enemy/Mogucchi.cpp | 231 +++++++++++++++++++++++++++- src/Game/Enemy/MogucchiHill.cpp | 5 + 4 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 include/Game/Enemy/MogucchiHill.hpp create mode 100644 src/Game/Enemy/MogucchiHill.cpp diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index 9fe6186c0..209d49697 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -1,14 +1,52 @@ #pragma once -#include "Game/NameObj/NameObj.hpp" #include "Game/LiveActor/LiveActor.hpp" +#include "JSystem/JGeometry/TVec.hpp" +class MogucchiHill; class Mogucchi : public LiveActor { public: Mogucchi(const char*); virtual ~Mogucchi(); + virtual void init(const JMapInfoIter& rIter); + virtual void initAfterPlacement(); + virtual void makeActorAppeared(); + virtual void kill(); + virtual void control(); + virtual void attackSensor(HitSensor* pSender, HitSensor* pReceiver); + virtual bool receiveMsgPlayerAttack(u32 msg, HitSensor* pSender, HitSensor* pReceiver); + + void exeStroll(); + void endStroll(); + void exeAppearDown(); + void exeDive(); + void exeScatter(); + void exeDie(); + void exeDown(); + void initSensor(); + void createMogucchiHill(); + void createHole(); + void updatePosition(); + void updateReferenceMtx(); + bool checkHipDrop() const; + void updateStrollSpeed(); + void reflectStarPointer2P(); + void makeEulerRotation(); + + MogucchiHill* mHill; + LiveActor* _90; + Mtx _94; + TVec3f _C4; + bool _D0; + f32 _D4; + TVec3f _D8; + f32 _E4; + f32 _E8; + f32 _EC; + bool _F0; + private: u8 mPad[(0xF4) - sizeof(LiveActor)]; }; diff --git a/include/Game/Enemy/MogucchiHill.hpp b/include/Game/Enemy/MogucchiHill.hpp new file mode 100644 index 000000000..4932d48aa --- /dev/null +++ b/include/Game/Enemy/MogucchiHill.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "Game/LiveActor/LiveActor.hpp" + +class HitSensor; + +class MogucchiHill : public LiveActor { +public: + MogucchiHill(LiveActor*, s32, const char*); + + virtual void init(); + virtual void control(); + + virtual void notifyAppearAttackToPlayer(HitSensor*, HitSensor*); + virtual void notifyWaitAttackToPlayer(HitSensor*, HitSensor*); + + void start(); + void end(); + void startNaturally(); + void endNaturally(); + + u32 _8C; + u32 _90; + u32 _94; + u32 _98; + + Mtx _9C; + + u8 _CC; + f32 _D0; + f32 _D4; + u32 _D8; + u32 _DC; + u32 _E0; + u32 _E4; + u8 _E8; + u32 _EC; + u32 _F0; + u32 _F4; +}; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 97077e3a6..fd34b0711 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -1,5 +1,232 @@ #include "Game/Enemy/Mogucchi.hpp" +#include "Game/Enemy/MogucchiHill.hpp" +#include "Game/LiveActor/LiveActor.hpp" +#include "Game/LiveActor/Nerve.hpp" +#include "Game/Util/ActorSensorUtil.hpp" +#include "Game/Util/ActorSwitchUtil.hpp" +#include "Game/Util/EffectUtil.hpp" +#include "Game/Util/GravityUtil.hpp" +#include "Game/Util/JMapUtil.hpp" +#include "Game/Util/JointUtil.hpp" +#include "Game/Util/LiveActorUtil.hpp" +#include "Game/Util/MathUtil.hpp" +#include "Game/Util/NerveUtil.hpp" +#include "Game/Util/ObjUtil.hpp" +#include "Game/Util/PlayerUtil.hpp" +#include "Game/Util/RailUtil.hpp" +#include "Game/Util/SoundUtil.hpp" +#include "Game/Util/StarPointerUtil.hpp" +#include "JSystem/JGeometry/TMatrix.hpp" +#include "JSystem/JGeometry/TVec.hpp" +#include "JSystem/JMath/JMath.hpp" +#include "math_types.hpp" +#include "revolution/mtx.h" +#include "revolution/types.h" -Mogucchi::Mogucchi(const char* pName) : LiveActor(pName) {} -Mogucchi::~Mogucchi() {} +namespace { + NEW_NERVE_ONEND(MogucchiNrvStroll, Mogucchi, Stroll, Stroll); + NEW_NERVE(MogucchiNrvAppearDown, Mogucchi, AppearDown); + NEW_NERVE(MogucchiNrvDown, Mogucchi, Down); + NEW_NERVE(MogucchiNrvDive, Mogucchi, Dive); + NEW_NERVE(MogucchiNrvScatter, Mogucchi, Scatter); + NEW_NERVE(MogucchiNrvDie, Mogucchi, Die); +} // namespace +namespace { + TVec3f sHeadOffset; +} + +Mogucchi::Mogucchi(const char* pName) + : LiveActor(pName), mHill(nullptr), _90(nullptr), _D0(false), _D4(0.0f), _D8(0.0f, 0.0f, 1.0f), _E4(0.0f), _E8(0.0f), _EC(5.0f), _F0(false) { +} + +Mogucchi::~Mogucchi() { +} + +void Mogucchi::init(const JMapInfoIter& rIter) { + MR::initDefaultPos(this, rIter); + MR::getJMapInfoArg0NoInit(rIter, &_EC); + initModelManagerWithAnm("Mogucchi", nullptr, false); + MR::connectToSceneEnemy(this); + initSensor(); + initEffectKeeper(1, nullptr, false); + MR::addEffect(this, "PointerTouchManual"); + MR::setEffectHostMtx(this, "PointerTouchManual", MR::getJointMtx(this, "Nose")); + initSound(4, false); + initRailRider(rIter); + MR::declareCoin(this, 1); + initNerve(&MogucchiNrvStroll::sInstance); + MR::useStageSwitchWriteDead(this, rIter); + + MR::initStarPointerTargetAtJoint(this, "Head", 83.0f, TVec3f(sHeadOffset)); + createMogucchiHill(); + createHole(); + MR::startBck(this, "Walk", nullptr); + MR::startBtp(this, "EyeOpen"); + calcAnim(); + makeActorAppeared(); +} + +void Mogucchi::initAfterPlacement() { + MR::moveCoordToNearestPos(this, mPosition); + // TODO: figure out _C4 + MR::calcGravityVector(this, MR::getRailPos(this), &mGravity, nullptr, nullptr); + updatePosition(); + updateReferenceMtx(); +} + +void Mogucchi::makeActorAppeared() { + LiveActor::makeActorAppeared(); + MR::showModel(this); + setNerve(&MogucchiNrvStroll::sInstance); + _90->makeActorAppeared(); + MR::showModel(_90); + MR::validateClipping(this); +} + +void Mogucchi::kill() { + LiveActor::kill(); + if (MR::isValidSwitchDead(this)) { + MR::onSwitchDead(this); + } + setNerve(&MogucchiNrvDie::sInstance); + + if (!MR::isDead(_90)) { + _90->kill(); + } +} + +void Mogucchi::control() { + // TODO: figure out inline + if (!isNerve(&MogucchiNrvScatter::sInstance) && isNerve(&MogucchiNrvDie::sInstance)) { + updateReferenceMtx(); + } +} + +bool Mogucchi::checkHipDrop() const { + // !MR::isPlayerHipDropLand() will not match + if (MR::isPlayerHipDropLand() == false) { + return false; + } + + return !(MR::calcDistanceToPlayer(this) > 800.0f); +} + +void Mogucchi::exeStroll() { + if (MR::isFirstStep(this)) { + MR::startBck(this, "Walk", nullptr); + MR::startBtp(this, "EyeOpen"); + MR::startBck(_90, "Walk", nullptr); + mHill->start(); + _E4 = 0.0f; + _E8 = _EC; + _F0 = false; + } + + MR::startLevelSound(this, "SE_EM_LV_MOGHILL_MOVE", -1, -1, -1); + updateStrollSpeed(); + reflectStarPointer2P(); + MR::moveCoord(this, _E8); + MR::calcGravityVector(this, MR::getRailPos(this), &_C4, nullptr, 0); + updatePosition(); + makeEulerRotation(); + + if (Mogucchi::checkHipDrop()) { + setNerve(&MogucchiNrvAppearDown::sInstance); + } +} + +void Mogucchi::exeDie() { + if (MR::isFirstStep(this)) { + MR::appearCoinPop(this, mPosition, 1); + MR::startSound(this, "SE_EM_EXPLODE_S", -1, -1); + MR::emitEffect(this, "Death"); + MR::hideModel(this); + MR::hideModel(_90); + } + + if (MR::isGreaterEqualStep(this, 60)) { + return kill(); + } +} + +void Mogucchi::exeDive() { + if (MR::isFirstStep(this)) { + MR::startBck(this, "Walk", nullptr); + MR::startBtp(this, "EyeOpen"); + MR::startBck(_90, "Walk", nullptr); + MR::startSound(this, "SE_EM_MOGUCCHI_HIDE", -1, -1); + } + + if (MR::isBckStopped(this)) { + setNerve(&MogucchiNrvStroll::sInstance); + } +} + +void Mogucchi::exeAppearDown() { + if (MR::isFirstStep(this)) { + MR::showModel(this); + MR::startBck(this, "SwoonStart", nullptr); + MR::startBtp(this, "EyeClose"); + MR::startBck(_90, "SwoonStart", nullptr); + MR::startSound(this, "SE_EM_MOGUCCHI_APPEAR", -1, -1); + MR::startSound(this, "SE_EV_MOGUCCHI_SWOON", -1, -1); + + // stack swap with the inner TVec3f + MR::setSensorOffset(this, "body", TVec3f(0.0f, 0.0f, 0.0f)); + MR::setSensorOffset(this, "spin", TVec3f(0.0f, 0.0f, 0.0f)); + } + + MR::startLevelSound(this, "SE_EM_LV_SWOON_S", -1, -1, -1); + MR::setNerveAtBckStopped(this, &MogucchiNrvDown::sInstance); +} + +void Mogucchi::exeDown() { + if (MR::isFirstStep(this)) { + MR::startBck(this, "Swoon", nullptr); + MR::startBtp(this, "EyeClose"); + MR::startBck(_90, "Swoon", nullptr); + } + MR::startLevelSound(this, "SE_EM_LV_SWOON_S", -1, -1, -1); + MR::setNerveAtStep(this, &MogucchiNrvDive::sInstance, 30); +} + +void Mogucchi::endStroll() { + MR::deleteEffect(this, "PointerTouchManual"); +} + +void Mogucchi::exeScatter() { + if (MR::isFirstStep(this)) { + mHill->end(); + MR::startBck(this, "PunchDown", nullptr); + MR::startBtp(this, "EyeClose"); + MR::startBck(_90, "PunchDown", nullptr); + MR::startBlowHitSound(this); + _D4 = 50.0f; + MR::invalidateClipping(this); + } + + TVec3f* c4 = &_C4; + + JMAVECScaleAdd(c4, &_D8, &_D8, -_C4.dot(_D8)); + MR::normalizeOrZero(&_D8); + + if (!MR::isNearZero(_D8)) { + TVec3f v2; + PSVECCrossProduct(c4, _D8, &v2); + + TRot3f mtx; + mtx.setXDirInline(v2); + mtx.setYDirInline(-_C4); + mtx.setZDirInline(-_D8); + mtx.getEulerXYZ(mRotation); + mRotation.mult(_180_PI); + } + + mPosition.add(_C4.scaleInline(-_D4).addOperatorInLine(_D8.multInLine(23.0f))); + _D4 -= 1.2f; + + if (MR::isGreaterEqualStep(this, 15)) { + setNerve(&MogucchiNrvDie::sInstance); + } +} diff --git a/src/Game/Enemy/MogucchiHill.cpp b/src/Game/Enemy/MogucchiHill.cpp new file mode 100644 index 000000000..3f39f95e7 --- /dev/null +++ b/src/Game/Enemy/MogucchiHill.cpp @@ -0,0 +1,5 @@ +#include "Game/Enemy/MogucchiHill.hpp" +#include "Game/LiveActor/LiveActor.hpp" + +MogucchiHill::MogucchiHill(LiveActor* pArg1, s32, const char* pName) : LiveActor(pName) { +} From c609ef20e4d5152ce48d096f4b83793fbbf9cba0 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Sat, 21 Mar 2026 15:00:47 +0100 Subject: [PATCH 03/16] Mogucchi 55% --- include/Game/Enemy/Mogucchi.hpp | 6 +++++- src/Game/Enemy/Mogucchi.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index 209d49697..035ea479c 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -1,6 +1,7 @@ #pragma once #include "Game/LiveActor/LiveActor.hpp" +#include "JSystem/JGeometry/TMatrix.hpp" #include "JSystem/JGeometry/TVec.hpp" class MogucchiHill; @@ -34,10 +35,13 @@ class Mogucchi : public LiveActor { void updateStrollSpeed(); void reflectStarPointer2P(); void makeEulerRotation(); + bool calcAttackDir(TVec3f*, const TVec3f&, const TVec3f&) const; + bool receiveAttackBySpinSensor(u32, HitSensor* pSender, HitSensor* pReceiver); + bool receiveAttackByBodySensor(u32, HitSensor* pSender, HitSensor* pReceiver); MogucchiHill* mHill; LiveActor* _90; - Mtx _94; + TMtx34f _94; TVec3f _C4; bool _D0; f32 _D4; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index fd34b0711..5c424cbae 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -1,5 +1,6 @@ #include "Game/Enemy/Mogucchi.hpp" #include "Game/Enemy/MogucchiHill.hpp" +#include "Game/LiveActor/HitSensor.hpp" #include "Game/LiveActor/LiveActor.hpp" #include "Game/LiveActor/Nerve.hpp" #include "Game/Util/ActorSensorUtil.hpp" @@ -38,6 +39,7 @@ namespace { Mogucchi::Mogucchi(const char* pName) : LiveActor(pName), mHill(nullptr), _90(nullptr), _D0(false), _D4(0.0f), _D8(0.0f, 0.0f, 1.0f), _E4(0.0f), _E8(0.0f), _EC(5.0f), _F0(false) { + _94.identity(); } Mogucchi::~Mogucchi() { @@ -230,3 +232,32 @@ void Mogucchi::exeScatter() { setNerve(&MogucchiNrvDie::sInstance); } } + +void Mogucchi::attackSensor(HitSensor* pSender, HitSensor* pReceiver) { + if (MR::isSensorPlayerOrRide(pReceiver) && (MR::isSensor(pSender, "body") || MR::isSensor(pSender, "head"))) { + if (!isNerve(&MogucchiNrvStroll::sInstance) || !MR::isOnGroundPlayer()) { + MR::sendMsgPush(pReceiver, pSender); + return; + } + + TVec3f attackDir; + calcAttackDir(&attackDir, pSender->mPosition, pReceiver->mPosition); + if (MR::sendMsgEnemyAttackStrongToDir(pReceiver, pSender, attackDir)) { + MR::shakeCameraNormal(); + return; + } + MR::sendMsgPush(pReceiver, pSender); + } +} + +bool Mogucchi::receiveMsgPlayerAttack(u32 msg, HitSensor* pSender, HitSensor* pReceiver) { + if (MR::isSensor(pReceiver, "spin")) { + return receiveAttackBySpinSensor(msg, pSender, pReceiver); + } + + return receiveAttackByBodySensor(msg, pSender, pReceiver); +} + +void Mogucchi::initSensor() { + LiveActor::initHitSensor(3); +} From 68de8b29767a4b3a9770609c78f8c1ff8f950a03 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:34:39 +0100 Subject: [PATCH 04/16] Mogucchi 69% --- include/Game/Enemy/Mogucchi.hpp | 13 ++-- include/Game/Enemy/MogucchiHill.hpp | 3 +- src/Game/Enemy/Mogucchi.cpp | 113 +++++++++++++++++++++++----- 3 files changed, 103 insertions(+), 26 deletions(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index 035ea479c..d26a4fa93 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -1,10 +1,9 @@ #pragma once #include "Game/LiveActor/LiveActor.hpp" -#include "JSystem/JGeometry/TMatrix.hpp" -#include "JSystem/JGeometry/TVec.hpp" class MogucchiHill; +class ModelObj; class Mogucchi : public LiveActor { public: @@ -39,17 +38,17 @@ class Mogucchi : public LiveActor { bool receiveAttackBySpinSensor(u32, HitSensor* pSender, HitSensor* pReceiver); bool receiveAttackByBodySensor(u32, HitSensor* pSender, HitSensor* pReceiver); - MogucchiHill* mHill; - LiveActor* _90; + /* 0x8C */ MogucchiHill* mHill; + /* 0x90 */ ModelObj* mHole; TMtx34f _94; TVec3f _C4; bool _D0; f32 _D4; TVec3f _D8; f32 _E4; - f32 _E8; - f32 _EC; - bool _F0; + /* 0xE8 */ f32 mStrollSpeed; + /* 0xEC */ f32 mMaxStrollSpeed; + /* 0xF0 */ bool mIsStoppedByP2; private: u8 mPad[(0xF4) - sizeof(LiveActor)]; diff --git a/include/Game/Enemy/MogucchiHill.hpp b/include/Game/Enemy/MogucchiHill.hpp index 4932d48aa..e37da641b 100644 --- a/include/Game/Enemy/MogucchiHill.hpp +++ b/include/Game/Enemy/MogucchiHill.hpp @@ -18,10 +18,11 @@ class MogucchiHill : public LiveActor { void end(); void startNaturally(); void endNaturally(); + void setAppearNum(s32); u32 _8C; u32 _90; - u32 _94; + s32 _94; u32 _98; Mtx _9C; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 5c424cbae..6ce46315a 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -2,7 +2,9 @@ #include "Game/Enemy/MogucchiHill.hpp" #include "Game/LiveActor/HitSensor.hpp" #include "Game/LiveActor/LiveActor.hpp" +#include "Game/LiveActor/ModelObj.hpp" #include "Game/LiveActor/Nerve.hpp" +#include "Game/Map/HitInfo.hpp" #include "Game/Util/ActorSensorUtil.hpp" #include "Game/Util/ActorSwitchUtil.hpp" #include "Game/Util/EffectUtil.hpp" @@ -10,8 +12,8 @@ #include "Game/Util/JMapUtil.hpp" #include "Game/Util/JointUtil.hpp" #include "Game/Util/LiveActorUtil.hpp" +#include "Game/Util/MapUtil.hpp" #include "Game/Util/MathUtil.hpp" -#include "Game/Util/NerveUtil.hpp" #include "Game/Util/ObjUtil.hpp" #include "Game/Util/PlayerUtil.hpp" #include "Game/Util/RailUtil.hpp" @@ -34,11 +36,13 @@ namespace { } // namespace namespace { - TVec3f sHeadOffset; -} + Vec sBodyOffset; + Vec sHeadOffset; +} // namespace Mogucchi::Mogucchi(const char* pName) - : LiveActor(pName), mHill(nullptr), _90(nullptr), _D0(false), _D4(0.0f), _D8(0.0f, 0.0f, 1.0f), _E4(0.0f), _E8(0.0f), _EC(5.0f), _F0(false) { + : LiveActor(pName), mHill(nullptr), mHole(nullptr), _D0(false), _D4(0.0f), _D8(0.0f, 0.0f, 1.0f), _E4(0.0f), mStrollSpeed(0.0f), + mMaxStrollSpeed(5.0f), mIsStoppedByP2(false) { _94.identity(); } @@ -47,7 +51,7 @@ Mogucchi::~Mogucchi() { void Mogucchi::init(const JMapInfoIter& rIter) { MR::initDefaultPos(this, rIter); - MR::getJMapInfoArg0NoInit(rIter, &_EC); + MR::getJMapInfoArg0NoInit(rIter, &mMaxStrollSpeed); initModelManagerWithAnm("Mogucchi", nullptr, false); MR::connectToSceneEnemy(this); initSensor(); @@ -81,8 +85,8 @@ void Mogucchi::makeActorAppeared() { LiveActor::makeActorAppeared(); MR::showModel(this); setNerve(&MogucchiNrvStroll::sInstance); - _90->makeActorAppeared(); - MR::showModel(_90); + mHole->makeActorAppeared(); + MR::showModel(mHole); MR::validateClipping(this); } @@ -93,8 +97,8 @@ void Mogucchi::kill() { } setNerve(&MogucchiNrvDie::sInstance); - if (!MR::isDead(_90)) { - _90->kill(); + if (!MR::isDead(mHole)) { + mHole->kill(); } } @@ -118,17 +122,17 @@ void Mogucchi::exeStroll() { if (MR::isFirstStep(this)) { MR::startBck(this, "Walk", nullptr); MR::startBtp(this, "EyeOpen"); - MR::startBck(_90, "Walk", nullptr); + MR::startBck(mHole, "Walk", nullptr); mHill->start(); _E4 = 0.0f; - _E8 = _EC; - _F0 = false; + mStrollSpeed = mMaxStrollSpeed; + mIsStoppedByP2 = false; } MR::startLevelSound(this, "SE_EM_LV_MOGHILL_MOVE", -1, -1, -1); updateStrollSpeed(); reflectStarPointer2P(); - MR::moveCoord(this, _E8); + MR::moveCoord(this, mStrollSpeed); MR::calcGravityVector(this, MR::getRailPos(this), &_C4, nullptr, 0); updatePosition(); makeEulerRotation(); @@ -144,7 +148,7 @@ void Mogucchi::exeDie() { MR::startSound(this, "SE_EM_EXPLODE_S", -1, -1); MR::emitEffect(this, "Death"); MR::hideModel(this); - MR::hideModel(_90); + MR::hideModel(mHole); } if (MR::isGreaterEqualStep(this, 60)) { @@ -156,7 +160,7 @@ void Mogucchi::exeDive() { if (MR::isFirstStep(this)) { MR::startBck(this, "Walk", nullptr); MR::startBtp(this, "EyeOpen"); - MR::startBck(_90, "Walk", nullptr); + MR::startBck(mHole, "Walk", nullptr); MR::startSound(this, "SE_EM_MOGUCCHI_HIDE", -1, -1); } @@ -170,7 +174,7 @@ void Mogucchi::exeAppearDown() { MR::showModel(this); MR::startBck(this, "SwoonStart", nullptr); MR::startBtp(this, "EyeClose"); - MR::startBck(_90, "SwoonStart", nullptr); + MR::startBck(mHole, "SwoonStart", nullptr); MR::startSound(this, "SE_EM_MOGUCCHI_APPEAR", -1, -1); MR::startSound(this, "SE_EV_MOGUCCHI_SWOON", -1, -1); @@ -187,7 +191,7 @@ void Mogucchi::exeDown() { if (MR::isFirstStep(this)) { MR::startBck(this, "Swoon", nullptr); MR::startBtp(this, "EyeClose"); - MR::startBck(_90, "Swoon", nullptr); + MR::startBck(mHole, "Swoon", nullptr); } MR::startLevelSound(this, "SE_EM_LV_SWOON_S", -1, -1, -1); MR::setNerveAtStep(this, &MogucchiNrvDive::sInstance, 30); @@ -202,7 +206,7 @@ void Mogucchi::exeScatter() { mHill->end(); MR::startBck(this, "PunchDown", nullptr); MR::startBtp(this, "EyeClose"); - MR::startBck(_90, "PunchDown", nullptr); + MR::startBck(mHole, "PunchDown", nullptr); MR::startBlowHitSound(this); _D4 = 50.0f; MR::invalidateClipping(this); @@ -260,4 +264,77 @@ bool Mogucchi::receiveMsgPlayerAttack(u32 msg, HitSensor* pSender, HitSensor* pR void Mogucchi::initSensor() { LiveActor::initHitSensor(3); + MR::addHitSensorAtJointEnemy(this, "head", "Head", 32, 83.0f, TVec3f(sHeadOffset)); + MR::addHitSensorAtJointEnemy(this, "body", "Spine", 32, 83.0f, TVec3f(sBodyOffset)); + MR::addHitSensorEnemy(this, "spin", 16, 180.0f, TVec3f(0.0f, 0.0f, 0.0f)); +} + +void Mogucchi::createMogucchiHill() { + s32 railLength = MR::getRailTotalLength(this) / 150.0f; + if (railLength > 20) { + railLength = 20; + } + + // "Mogucchi hill" + mHill = new MogucchiHill(this, railLength, "モグッチ塚"); + mHill->initWithoutIter(); + if (railLength > 5) { + mHill->setAppearNum(mHill->_94 - 5); + } + + MogucchiHill* hill = mHill; + hill->_D0 = 80.0f; + hill->_D4 = 100.0f; +} + +void Mogucchi::updateStrollSpeed() { + if (!(mStrollSpeed < mMaxStrollSpeed)) { + return; + } + + mStrollSpeed += 0.1f; + if (mStrollSpeed > mMaxStrollSpeed) { + mStrollSpeed = mMaxStrollSpeed; + } +} + +void Mogucchi::reflectStarPointer2P() { + // "Weak" + if (MR::isStarPointerPointing2POnPressButton(this, "弱", true, false)) { + if (!mIsStoppedByP2) { + mIsStoppedByP2 = true; + MR::startDPDHitSound(); + MR::emitEffectWithScale(this, "PointerTouchManual", 1.4f, -1); + } + + mStrollSpeed = 0.0f; + MR::startDPDFreezeLevelSound(this); + return; + } + + if (!mIsStoppedByP2) { + return; + } + + mIsStoppedByP2 = false; + MR::deleteEffect(this, "PointerTouchManual"); +} + +void Mogucchi::updatePosition() { + Triangle triangle = Triangle(); + + TVec3f v1; + _D0 = MR::getFirstPolyOnLineToMap(&v1, &triangle, MR::getRailPos(this), _C4.scaleInline(1000.0f)); + + if (_D0) { + mPosition.set(v1); + } else { + mPosition.set(MR::getRailPos(this)); + } +} + +void Mogucchi::createHole() { + // "Mogucchi hole" + mHole = new ModelObj("モグッチ穴", "MogucchiHole", _94, 10, -2, -2, false); + mHole->initWithoutIter(); } From 7a091d759ff42b89c3268326fe075ad4d5ffa027 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Sat, 28 Mar 2026 16:33:46 +0100 Subject: [PATCH 05/16] Mogucchi 84% --- include/Game/Enemy/Mogucchi.hpp | 9 ++-- src/Game/Enemy/Mogucchi.cpp | 75 ++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index d26a4fa93..502a57c2b 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -34,9 +34,10 @@ class Mogucchi : public LiveActor { void updateStrollSpeed(); void reflectStarPointer2P(); void makeEulerRotation(); - bool calcAttackDir(TVec3f*, const TVec3f&, const TVec3f&) const; - bool receiveAttackBySpinSensor(u32, HitSensor* pSender, HitSensor* pReceiver); - bool receiveAttackByBodySensor(u32, HitSensor* pSender, HitSensor* pReceiver); + void calcAttackDir(TVec3f*, const TVec3f&, const TVec3f&) const; + bool receiveAttackBySpinSensor(u32 msg, HitSensor* pSender, HitSensor* pReceiver); + bool receiveAttackByBodySensor(u32 msg, HitSensor* pSender, HitSensor* pReceiver); + void calcScatterVec(const TVec3f&, const TVec3f&); /* 0x8C */ MogucchiHill* mHill; /* 0x90 */ ModelObj* mHole; @@ -44,7 +45,7 @@ class Mogucchi : public LiveActor { TVec3f _C4; bool _D0; f32 _D4; - TVec3f _D8; + /* 0xD8 */ TVec3f mScatterVec; f32 _E4; /* 0xE8 */ f32 mStrollSpeed; /* 0xEC */ f32 mMaxStrollSpeed; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 6ce46315a..8e5b9916f 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -14,6 +14,7 @@ #include "Game/Util/LiveActorUtil.hpp" #include "Game/Util/MapUtil.hpp" #include "Game/Util/MathUtil.hpp" +#include "Game/Util/MtxUtil.hpp" #include "Game/Util/ObjUtil.hpp" #include "Game/Util/PlayerUtil.hpp" #include "Game/Util/RailUtil.hpp" @@ -41,7 +42,7 @@ namespace { } // namespace Mogucchi::Mogucchi(const char* pName) - : LiveActor(pName), mHill(nullptr), mHole(nullptr), _D0(false), _D4(0.0f), _D8(0.0f, 0.0f, 1.0f), _E4(0.0f), mStrollSpeed(0.0f), + : LiveActor(pName), mHill(nullptr), mHole(nullptr), _D0(false), _D4(0.0f), mScatterVec(0.0f, 0.0f, 1.0f), _E4(0.0f), mStrollSpeed(0.0f), mMaxStrollSpeed(5.0f), mIsStoppedByP2(false) { _94.identity(); } @@ -214,22 +215,22 @@ void Mogucchi::exeScatter() { TVec3f* c4 = &_C4; - JMAVECScaleAdd(c4, &_D8, &_D8, -_C4.dot(_D8)); - MR::normalizeOrZero(&_D8); + JMAVECScaleAdd(c4, &mScatterVec, &mScatterVec, -_C4.dot(mScatterVec)); + MR::normalizeOrZero(&mScatterVec); - if (!MR::isNearZero(_D8)) { + if (!MR::isNearZero(mScatterVec)) { TVec3f v2; - PSVECCrossProduct(c4, _D8, &v2); + PSVECCrossProduct(c4, mScatterVec, &v2); TRot3f mtx; mtx.setXDirInline(v2); mtx.setYDirInline(-_C4); - mtx.setZDirInline(-_D8); + mtx.setZDirInline(-mScatterVec); mtx.getEulerXYZ(mRotation); mRotation.mult(_180_PI); } - mPosition.add(_C4.scaleInline(-_D4).addOperatorInLine(_D8.multInLine(23.0f))); + mPosition.add(_C4.scaleInline(-_D4).addOperatorInLine(mScatterVec.multInLine(23.0f))); _D4 -= 1.2f; if (MR::isGreaterEqualStep(this, 15)) { @@ -338,3 +339,63 @@ void Mogucchi::createHole() { mHole = new ModelObj("モグッチ穴", "MogucchiHole", _94, 10, -2, -2, false); mHole->initWithoutIter(); } + +void Mogucchi::calcAttackDir(TVec3f* pDir, const TVec3f& senderPos, const TVec3f& receiverPos) const { + pDir->sub(receiverPos, senderPos); + const TVec3f* c4 = &_C4; + JMAVECScaleAdd(c4, pDir, pDir, -c4->dot(*pDir)); + MR::normalizeOrZero(pDir); + + if (MR::isNearZero(*pDir, 0.001f)) { + pDir->set< f32 >(getBaseMtx()[0][1], getBaseMtx()[1][1], getBaseMtx()[2][1]); + } + + pDir->add(-_C4); + MR::normalize(pDir); +} + +void Mogucchi::makeEulerRotation() { + TPos3f mtx; + MR::makeMtxUpFront(&mtx, -_C4, MR::getRailDirection(this)); + mtx.getEulerXYZ(mRotation); + mRotation.mult(_180_PI); +} + +void Mogucchi::calcScatterVec(const TVec3f& p1, const TVec3f& p2) { + mScatterVec.sub(p2, p1); + const TVec3f* c4 = &_C4; + JMAVECScaleAdd(c4, mScatterVec, mScatterVec, -c4->dot(mScatterVec)); + MR::normalizeOrZero(&mScatterVec); +} + +bool Mogucchi::receiveAttackBySpinSensor(u32 msg, HitSensor* pSender, HitSensor* pReceiver) { + if (!MR::isMsgPlayerSpinAttack(msg)) { + return false; + } + + if (isNerve(&MogucchiNrvStroll::sInstance)) { + MR::startSound(this, "SE_EM_MOGUCCHI_REFRECT", -1, -1); + MR::sendMsgEnemyAttackCounterSpin(pSender, pReceiver); + return true; + } + + bool isDown = false; + if (isNerve(&MogucchiNrvDown::sInstance) || isNerve(&MogucchiNrvAppearDown::sInstance) || isNerve(&MogucchiNrvDive::sInstance)) { + isDown = true; + } + + if (!isDown) { + return false; + } + + if (isNerve(&MogucchiNrvAppearDown::sInstance) && MR::isLessStep(this, 10)) { + return false; + } + + MR::stopScene(8); + MR::tryRumblePadMiddle(this, 0); + calcScatterVec(pSender->mPosition, pReceiver->mPosition); + setNerve(&MogucchiNrvScatter::sInstance); + + return true; +} From 645ac02d9e3c7d42208b89ddd17d291041b7ae07 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:04:37 +0200 Subject: [PATCH 06/16] Mogucchi 93% --- include/Game/Enemy/Mogucchi.hpp | 2 +- src/Game/Enemy/Mogucchi.cpp | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index 502a57c2b..942bf2fc7 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -41,7 +41,7 @@ class Mogucchi : public LiveActor { /* 0x8C */ MogucchiHill* mHill; /* 0x90 */ ModelObj* mHole; - TMtx34f _94; + TRot3f _94; TVec3f _C4; bool _D0; f32 _D4; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 8e5b9916f..ad9410856 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -399,3 +399,54 @@ bool Mogucchi::receiveAttackBySpinSensor(u32 msg, HitSensor* pSender, HitSensor* return true; } + +bool Mogucchi::receiveAttackByBodySensor(u32 msg, HitSensor* pSender, HitSensor* pReceiver) { + if (MR::isMsgPlayerSpinAttack(msg)) { + return false; + } + + if (!isNerve(&MogucchiNrvScatter::sInstance) && !isNerve(&MogucchiNrvDie::sInstance) && MR::isMsgStarPieceAttack(msg)) { + setNerve(&MogucchiNrvAppearDown::sInstance); + return true; + } + + bool isDown = isNerve(&MogucchiNrvDown::sInstance) || isNerve(&MogucchiNrvAppearDown::sInstance) || isNerve(&MogucchiNrvDive::sInstance); + + if (!isDown) { + if (MR::isMsgPlayerTrample(msg)) { + MR::startSound(this, "SE_EM_MOGUCCHI_REFRECT", -1, -1); + return true; + } + + return false; + } + + if (isNerve(&MogucchiNrvAppearDown::sInstance) && MR::isLessStep(this, 10)) { + return false; + } + + if (MR::isMsgPlayerTrample(msg) || MR::isMsgPlayerHipDrop(msg)) { + MR::startBck(this, "Bounce", nullptr); + MR::startBtp(this, "EyeOpen"); + return true; + } + + if (MR::isMsgPlayerHitAll(msg)) { + MR::stopScene(8); + MR::tryRumblePadMiddle(this, 0); + calcScatterVec(pSender->mPosition, pReceiver->mPosition); + setNerve(&MogucchiNrvScatter::sInstance); + return true; + } + + return false; +} + +void Mogucchi::updateReferenceMtx() { + TVec3f v1(mRotation); + v1.scale(PI_180); + + // Some inlined TPos3f function involving _94? + + mHole->mPosition.set(mPosition); +} From aa499f0531b12d3a2e9489646ee3bbbfb32aa306 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:16:48 +0200 Subject: [PATCH 07/16] Mogucchi data match --- src/Game/Enemy/Mogucchi.cpp | 58 ++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index ad9410856..d4126df18 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -143,33 +143,6 @@ void Mogucchi::exeStroll() { } } -void Mogucchi::exeDie() { - if (MR::isFirstStep(this)) { - MR::appearCoinPop(this, mPosition, 1); - MR::startSound(this, "SE_EM_EXPLODE_S", -1, -1); - MR::emitEffect(this, "Death"); - MR::hideModel(this); - MR::hideModel(mHole); - } - - if (MR::isGreaterEqualStep(this, 60)) { - return kill(); - } -} - -void Mogucchi::exeDive() { - if (MR::isFirstStep(this)) { - MR::startBck(this, "Walk", nullptr); - MR::startBtp(this, "EyeOpen"); - MR::startBck(mHole, "Walk", nullptr); - MR::startSound(this, "SE_EM_MOGUCCHI_HIDE", -1, -1); - } - - if (MR::isBckStopped(this)) { - setNerve(&MogucchiNrvStroll::sInstance); - } -} - void Mogucchi::exeAppearDown() { if (MR::isFirstStep(this)) { MR::showModel(this); @@ -198,8 +171,17 @@ void Mogucchi::exeDown() { MR::setNerveAtStep(this, &MogucchiNrvDive::sInstance, 30); } -void Mogucchi::endStroll() { - MR::deleteEffect(this, "PointerTouchManual"); +void Mogucchi::exeDive() { + if (MR::isFirstStep(this)) { + MR::startBck(this, "Hide", nullptr); + MR::startBtp(this, "EyeOpen"); + MR::startBck(mHole, "Hide", nullptr); + MR::startSound(this, "SE_EM_MOGUCCHI_HIDE", -1, -1); + } + + if (MR::isBckStopped(this)) { + setNerve(&MogucchiNrvStroll::sInstance); + } } void Mogucchi::exeScatter() { @@ -238,6 +220,24 @@ void Mogucchi::exeScatter() { } } +void Mogucchi::exeDie() { + if (MR::isFirstStep(this)) { + MR::appearCoinPop(this, mPosition, 1); + MR::startSound(this, "SE_EM_EXPLODE_S", -1, -1); + MR::emitEffect(this, "Death"); + MR::hideModel(this); + MR::hideModel(mHole); + } + + if (MR::isGreaterEqualStep(this, 60)) { + return kill(); + } +} + +void Mogucchi::endStroll() { + MR::deleteEffect(this, "PointerTouchManual"); +} + void Mogucchi::attackSensor(HitSensor* pSender, HitSensor* pReceiver) { if (MR::isSensorPlayerOrRide(pReceiver) && (MR::isSensor(pSender, "body") || MR::isSensor(pSender, "head"))) { if (!isNerve(&MogucchiNrvStroll::sInstance) || !MR::isOnGroundPlayer()) { From 0838787110b6d6b892b85a8dbbe110da0296343c Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:26:00 +0200 Subject: [PATCH 08/16] Mogucchi 97% --- include/Game/Enemy/Mogucchi.hpp | 2 +- src/Game/Enemy/Mogucchi.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index 942bf2fc7..b9b665b34 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -41,7 +41,7 @@ class Mogucchi : public LiveActor { /* 0x8C */ MogucchiHill* mHill; /* 0x90 */ ModelObj* mHole; - TRot3f _94; + TPos3f _94; TVec3f _C4; bool _D0; f32 _D4; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index d4126df18..ed1ab2952 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -104,10 +104,11 @@ void Mogucchi::kill() { } void Mogucchi::control() { - // TODO: figure out inline - if (!isNerve(&MogucchiNrvScatter::sInstance) && isNerve(&MogucchiNrvDie::sInstance)) { - updateReferenceMtx(); + if (isNerve(&MogucchiNrvScatter::sInstance) || isNerve(&MogucchiNrvDie::sInstance)) { + return; } + + updateReferenceMtx(); } bool Mogucchi::checkHipDrop() const { @@ -447,6 +448,8 @@ void Mogucchi::updateReferenceMtx() { v1.scale(PI_180); // Some inlined TPos3f function involving _94? + _94.makeMatrixFromRotAxesInline(v1.x, v1.y, v1.z); + _94.setTransInline(mPosition); mHole->mPosition.set(mPosition); } From 2a970f5ec60781fec9ff79d616bf46e44d633f17 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:26:18 +0200 Subject: [PATCH 09/16] Match Mogucchi::initAfterPlacement --- src/Game/Enemy/Mogucchi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index ed1ab2952..7464b457e 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -77,7 +77,7 @@ void Mogucchi::init(const JMapInfoIter& rIter) { void Mogucchi::initAfterPlacement() { MR::moveCoordToNearestPos(this, mPosition); // TODO: figure out _C4 - MR::calcGravityVector(this, MR::getRailPos(this), &mGravity, nullptr, nullptr); + MR::calcGravityVector(this, MR::getRailPos(this), &_C4, nullptr, nullptr); updatePosition(); updateReferenceMtx(); } From 4f23d3040696df54d08dde7c7fb16fd27b239c82 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:31:26 +0200 Subject: [PATCH 10/16] Fix float mismatch in Mogucchi::updateReferenceMtx() --- src/Game/Enemy/Mogucchi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 7464b457e..8c78e11b3 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -445,9 +445,9 @@ bool Mogucchi::receiveAttackByBodySensor(u32 msg, HitSensor* pSender, HitSensor* void Mogucchi::updateReferenceMtx() { TVec3f v1(mRotation); - v1.scale(PI_180); + // Using PI_180 will mismatch the float value by 1 least significant bit + v1.scale(57.295776); - // Some inlined TPos3f function involving _94? _94.makeMatrixFromRotAxesInline(v1.x, v1.y, v1.z); _94.setTransInline(mPosition); From c65b11df5f9a1f68d2ad68312b8d5fceb2fe75ce Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:36:21 +0200 Subject: [PATCH 11/16] Name Mogucchi _9C --- include/Game/Enemy/Mogucchi.hpp | 2 +- src/Game/Enemy/Mogucchi.cpp | 29 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index b9b665b34..8e35a082f 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -42,7 +42,7 @@ class Mogucchi : public LiveActor { /* 0x8C */ MogucchiHill* mHill; /* 0x90 */ ModelObj* mHole; TPos3f _94; - TVec3f _C4; + /* 0x9C */ TVec3f mRailGravity; bool _D0; f32 _D4; /* 0xD8 */ TVec3f mScatterVec; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 8c78e11b3..95c7f788d 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -76,8 +76,7 @@ void Mogucchi::init(const JMapInfoIter& rIter) { void Mogucchi::initAfterPlacement() { MR::moveCoordToNearestPos(this, mPosition); - // TODO: figure out _C4 - MR::calcGravityVector(this, MR::getRailPos(this), &_C4, nullptr, nullptr); + MR::calcGravityVector(this, MR::getRailPos(this), &mRailGravity, nullptr, nullptr); updatePosition(); updateReferenceMtx(); } @@ -135,7 +134,7 @@ void Mogucchi::exeStroll() { updateStrollSpeed(); reflectStarPointer2P(); MR::moveCoord(this, mStrollSpeed); - MR::calcGravityVector(this, MR::getRailPos(this), &_C4, nullptr, 0); + MR::calcGravityVector(this, MR::getRailPos(this), &mRailGravity, nullptr, 0); updatePosition(); makeEulerRotation(); @@ -196,24 +195,24 @@ void Mogucchi::exeScatter() { MR::invalidateClipping(this); } - TVec3f* c4 = &_C4; + TVec3f* railGravity = &mRailGravity; - JMAVECScaleAdd(c4, &mScatterVec, &mScatterVec, -_C4.dot(mScatterVec)); + JMAVECScaleAdd(railGravity, &mScatterVec, &mScatterVec, -mRailGravity.dot(mScatterVec)); MR::normalizeOrZero(&mScatterVec); if (!MR::isNearZero(mScatterVec)) { TVec3f v2; - PSVECCrossProduct(c4, mScatterVec, &v2); + PSVECCrossProduct(railGravity, mScatterVec, &v2); TRot3f mtx; mtx.setXDirInline(v2); - mtx.setYDirInline(-_C4); + mtx.setYDirInline(-mRailGravity); mtx.setZDirInline(-mScatterVec); mtx.getEulerXYZ(mRotation); mRotation.mult(_180_PI); } - mPosition.add(_C4.scaleInline(-_D4).addOperatorInLine(mScatterVec.multInLine(23.0f))); + mPosition.add(mRailGravity.scaleInline(-_D4).addOperatorInLine(mScatterVec.multInLine(23.0f))); _D4 -= 1.2f; if (MR::isGreaterEqualStep(this, 15)) { @@ -326,7 +325,7 @@ void Mogucchi::updatePosition() { Triangle triangle = Triangle(); TVec3f v1; - _D0 = MR::getFirstPolyOnLineToMap(&v1, &triangle, MR::getRailPos(this), _C4.scaleInline(1000.0f)); + _D0 = MR::getFirstPolyOnLineToMap(&v1, &triangle, MR::getRailPos(this), mRailGravity.scaleInline(1000.0f)); if (_D0) { mPosition.set(v1); @@ -343,29 +342,29 @@ void Mogucchi::createHole() { void Mogucchi::calcAttackDir(TVec3f* pDir, const TVec3f& senderPos, const TVec3f& receiverPos) const { pDir->sub(receiverPos, senderPos); - const TVec3f* c4 = &_C4; - JMAVECScaleAdd(c4, pDir, pDir, -c4->dot(*pDir)); + const TVec3f* railGravity = &mRailGravity; + JMAVECScaleAdd(railGravity, pDir, pDir, -railGravity->dot(*pDir)); MR::normalizeOrZero(pDir); if (MR::isNearZero(*pDir, 0.001f)) { pDir->set< f32 >(getBaseMtx()[0][1], getBaseMtx()[1][1], getBaseMtx()[2][1]); } - pDir->add(-_C4); + pDir->add(-mRailGravity); MR::normalize(pDir); } void Mogucchi::makeEulerRotation() { TPos3f mtx; - MR::makeMtxUpFront(&mtx, -_C4, MR::getRailDirection(this)); + MR::makeMtxUpFront(&mtx, -mRailGravity, MR::getRailDirection(this)); mtx.getEulerXYZ(mRotation); mRotation.mult(_180_PI); } void Mogucchi::calcScatterVec(const TVec3f& p1, const TVec3f& p2) { mScatterVec.sub(p2, p1); - const TVec3f* c4 = &_C4; - JMAVECScaleAdd(c4, mScatterVec, mScatterVec, -c4->dot(mScatterVec)); + const TVec3f* railGravity = &mRailGravity; + JMAVECScaleAdd(railGravity, mScatterVec, mScatterVec, -railGravity->dot(mScatterVec)); MR::normalizeOrZero(&mScatterVec); } From 2ca93a2757ff8b1617bace38217c6e3f8363e4b9 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:38:06 +0200 Subject: [PATCH 12/16] Name Mogucchi _D0 --- include/Game/Enemy/Mogucchi.hpp | 2 +- src/Game/Enemy/Mogucchi.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index 8e35a082f..2cb9e25a0 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -43,7 +43,7 @@ class Mogucchi : public LiveActor { /* 0x90 */ ModelObj* mHole; TPos3f _94; /* 0x9C */ TVec3f mRailGravity; - bool _D0; + /* 0xD0 */ bool mGrounded; f32 _D4; /* 0xD8 */ TVec3f mScatterVec; f32 _E4; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 95c7f788d..54d9d29a0 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -42,7 +42,7 @@ namespace { } // namespace Mogucchi::Mogucchi(const char* pName) - : LiveActor(pName), mHill(nullptr), mHole(nullptr), _D0(false), _D4(0.0f), mScatterVec(0.0f, 0.0f, 1.0f), _E4(0.0f), mStrollSpeed(0.0f), + : LiveActor(pName), mHill(nullptr), mHole(nullptr), mGrounded(false), _D4(0.0f), mScatterVec(0.0f, 0.0f, 1.0f), _E4(0.0f), mStrollSpeed(0.0f), mMaxStrollSpeed(5.0f), mIsStoppedByP2(false) { _94.identity(); } @@ -325,9 +325,9 @@ void Mogucchi::updatePosition() { Triangle triangle = Triangle(); TVec3f v1; - _D0 = MR::getFirstPolyOnLineToMap(&v1, &triangle, MR::getRailPos(this), mRailGravity.scaleInline(1000.0f)); + mGrounded = MR::getFirstPolyOnLineToMap(&v1, &triangle, MR::getRailPos(this), mRailGravity.scaleInline(1000.0f)); - if (_D0) { + if (mGrounded) { mPosition.set(v1); } else { mPosition.set(MR::getRailPos(this)); From 905b478f6488b3790fb9e910d0f3f130668c60a6 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Thu, 2 Apr 2026 17:55:50 +0200 Subject: [PATCH 13/16] More Mogucchi member documentation --- include/Game/Enemy/Mogucchi.hpp | 8 ++++---- src/Game/Enemy/Mogucchi.cpp | 34 ++++++++++++++++----------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index 2cb9e25a0..a42c32077 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -41,11 +41,11 @@ class Mogucchi : public LiveActor { /* 0x8C */ MogucchiHill* mHill; /* 0x90 */ ModelObj* mHole; - TPos3f _94; - /* 0x9C */ TVec3f mRailGravity; + /* 0x94 */ TPos3f mNewHolePos; + /* 0xC4 */ TVec3f mRailGravity; /* 0xD0 */ bool mGrounded; - f32 _D4; - /* 0xD8 */ TVec3f mScatterVec; + /* 0xD4 */ f32 mScatterPropulsionSpeed; + /* 0xD8 */ TVec3f mScatterNormal; f32 _E4; /* 0xE8 */ f32 mStrollSpeed; /* 0xEC */ f32 mMaxStrollSpeed; diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 54d9d29a0..477650b8e 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -42,9 +42,9 @@ namespace { } // namespace Mogucchi::Mogucchi(const char* pName) - : LiveActor(pName), mHill(nullptr), mHole(nullptr), mGrounded(false), _D4(0.0f), mScatterVec(0.0f, 0.0f, 1.0f), _E4(0.0f), mStrollSpeed(0.0f), - mMaxStrollSpeed(5.0f), mIsStoppedByP2(false) { - _94.identity(); + : LiveActor(pName), mHill(nullptr), mHole(nullptr), mGrounded(false), mScatterPropulsionSpeed(0.0f), mScatterNormal(0.0f, 0.0f, 1.0f), _E4(0.0f), + mStrollSpeed(0.0f), mMaxStrollSpeed(5.0f), mIsStoppedByP2(false) { + mNewHolePos.identity(); } Mogucchi::~Mogucchi() { @@ -191,29 +191,29 @@ void Mogucchi::exeScatter() { MR::startBtp(this, "EyeClose"); MR::startBck(mHole, "PunchDown", nullptr); MR::startBlowHitSound(this); - _D4 = 50.0f; + mScatterPropulsionSpeed = 50.0f; MR::invalidateClipping(this); } TVec3f* railGravity = &mRailGravity; - JMAVECScaleAdd(railGravity, &mScatterVec, &mScatterVec, -mRailGravity.dot(mScatterVec)); - MR::normalizeOrZero(&mScatterVec); + JMAVECScaleAdd(railGravity, &mScatterNormal, &mScatterNormal, -mRailGravity.dot(mScatterNormal)); + MR::normalizeOrZero(&mScatterNormal); - if (!MR::isNearZero(mScatterVec)) { + if (!MR::isNearZero(mScatterNormal)) { TVec3f v2; - PSVECCrossProduct(railGravity, mScatterVec, &v2); + PSVECCrossProduct(railGravity, mScatterNormal, &v2); TRot3f mtx; mtx.setXDirInline(v2); mtx.setYDirInline(-mRailGravity); - mtx.setZDirInline(-mScatterVec); + mtx.setZDirInline(-mScatterNormal); mtx.getEulerXYZ(mRotation); mRotation.mult(_180_PI); } - mPosition.add(mRailGravity.scaleInline(-_D4).addOperatorInLine(mScatterVec.multInLine(23.0f))); - _D4 -= 1.2f; + mPosition.add(mRailGravity.scaleInline(-mScatterPropulsionSpeed).addOperatorInLine(mScatterNormal.multInLine(23.0f))); + mScatterPropulsionSpeed -= 1.2f; if (MR::isGreaterEqualStep(this, 15)) { setNerve(&MogucchiNrvDie::sInstance); @@ -336,7 +336,7 @@ void Mogucchi::updatePosition() { void Mogucchi::createHole() { // "Mogucchi hole" - mHole = new ModelObj("モグッチ穴", "MogucchiHole", _94, 10, -2, -2, false); + mHole = new ModelObj("モグッチ穴", "MogucchiHole", mNewHolePos, 10, -2, -2, false); mHole->initWithoutIter(); } @@ -362,10 +362,10 @@ void Mogucchi::makeEulerRotation() { } void Mogucchi::calcScatterVec(const TVec3f& p1, const TVec3f& p2) { - mScatterVec.sub(p2, p1); + mScatterNormal.sub(p2, p1); const TVec3f* railGravity = &mRailGravity; - JMAVECScaleAdd(railGravity, mScatterVec, mScatterVec, -railGravity->dot(mScatterVec)); - MR::normalizeOrZero(&mScatterVec); + JMAVECScaleAdd(railGravity, mScatterNormal, mScatterNormal, -railGravity->dot(mScatterNormal)); + MR::normalizeOrZero(&mScatterNormal); } bool Mogucchi::receiveAttackBySpinSensor(u32 msg, HitSensor* pSender, HitSensor* pReceiver) { @@ -447,8 +447,8 @@ void Mogucchi::updateReferenceMtx() { // Using PI_180 will mismatch the float value by 1 least significant bit v1.scale(57.295776); - _94.makeMatrixFromRotAxesInline(v1.x, v1.y, v1.z); - _94.setTransInline(mPosition); + mNewHolePos.makeMatrixFromRotAxesInline(v1.x, v1.y, v1.z); + mNewHolePos.setTransInline(mPosition); mHole->mPosition.set(mPosition); } From 44bb9afc1d22aa11402496f99b77affde72660f7 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Fri, 3 Apr 2026 15:20:32 +0200 Subject: [PATCH 14/16] Mogucchi NamoObjFactory regression fix --- include/Game/Enemy/Mogucchi.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/Game/Enemy/Mogucchi.hpp b/include/Game/Enemy/Mogucchi.hpp index a42c32077..526f772b2 100644 --- a/include/Game/Enemy/Mogucchi.hpp +++ b/include/Game/Enemy/Mogucchi.hpp @@ -50,7 +50,4 @@ class Mogucchi : public LiveActor { /* 0xE8 */ f32 mStrollSpeed; /* 0xEC */ f32 mMaxStrollSpeed; /* 0xF0 */ bool mIsStoppedByP2; - -private: - u8 mPad[(0xF4) - sizeof(LiveActor)]; }; From 36a2dccfd0b0de95e994b8c45103271609ffb763 Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Tue, 7 Apr 2026 21:45:11 +0200 Subject: [PATCH 15/16] Remove redundant include in `MogucchiHill.cpp` --- src/Game/Enemy/MogucchiHill.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Game/Enemy/MogucchiHill.cpp b/src/Game/Enemy/MogucchiHill.cpp index 3f39f95e7..3d8dbcc79 100644 --- a/src/Game/Enemy/MogucchiHill.cpp +++ b/src/Game/Enemy/MogucchiHill.cpp @@ -1,5 +1,4 @@ #include "Game/Enemy/MogucchiHill.hpp" -#include "Game/LiveActor/LiveActor.hpp" MogucchiHill::MogucchiHill(LiveActor* pArg1, s32, const char* pName) : LiveActor(pName) { } From a2baf0ea3f2c863419337665b90edce08d1c04fc Mon Sep 17 00:00:00 2001 From: NextOp-Next <58630743+NextOp-Next@users.noreply.github.com> Date: Tue, 7 Apr 2026 21:47:34 +0200 Subject: [PATCH 16/16] Simplify isDown declaration in `Mogucchi::receuceAttackBySpinSensor` --- src/Game/Enemy/Mogucchi.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Game/Enemy/Mogucchi.cpp b/src/Game/Enemy/Mogucchi.cpp index 477650b8e..19c6c1fd9 100644 --- a/src/Game/Enemy/Mogucchi.cpp +++ b/src/Game/Enemy/Mogucchi.cpp @@ -379,10 +379,7 @@ bool Mogucchi::receiveAttackBySpinSensor(u32 msg, HitSensor* pSender, HitSensor* return true; } - bool isDown = false; - if (isNerve(&MogucchiNrvDown::sInstance) || isNerve(&MogucchiNrvAppearDown::sInstance) || isNerve(&MogucchiNrvDive::sInstance)) { - isDown = true; - } + bool isDown = isNerve(&MogucchiNrvDown::sInstance) || isNerve(&MogucchiNrvAppearDown::sInstance) || isNerve(&MogucchiNrvDive::sInstance); if (!isDown) { return false;