From 962e9c447404ebc671f2f638a23ab3ac1cd1ec68 Mon Sep 17 00:00:00 2001 From: MJ Date: Fri, 22 May 2026 17:40:10 +1000 Subject: [PATCH 01/29] Start adding templated object creation functions for Geography Objects that exist as part of the `GeographyObjMgr`. Something useful is that each of these functions contains the size that the respective class it calls should be, meaning we can determine if the classes being called are missing members. Nice! --- src/Sato/GeographyObjMgr.cpp | 222 +++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index e69de29b..52d1954e 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -0,0 +1,222 @@ +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/Objects/GeoAirJet.h" +#include "Kaneshige/Objects/GeoBombCar.h" +#include "Kaneshige/Objects/GeoBus.h" +#include "Kaneshige/Objects/GeoCannon.h" +#include "Kaneshige/Objects/GeoCar.h" +#include "Kaneshige/Objects/GeoCarShadow.h" +#include "Kaneshige/Objects/GeoDkCloud.h" +#include "Kaneshige/Objects/GeoHanaBody.h" +#include "Kaneshige/Objects/GeoHanaCar.h" +#include "Kaneshige/Objects/GeoItemCar.h" +#include "Kaneshige/Objects/GeoItemGen.h" +#include "Kaneshige/Objects/GeoKinoCar.h" +#include "Kaneshige/Objects/GeoKinojii.h" +#include "Kaneshige/Objects/GeoKuriCar.h" +#include "Kaneshige/Objects/GeoKuribo.h" +#include "Kaneshige/Objects/GeoNormCar.h" +#include "Kaneshige/Objects/GeoPuller.h" +#include "Kaneshige/Objects/GeoRabbitMark.h" +#include "Kaneshige/Objects/GeoShimmer.h" +#include "Kaneshige/Objects/GeoShine.h" +#include "Kaneshige/Objects/GeoSignal.h" +#include "Kaneshige/Objects/GeoSoundGen.h" +#include "Kaneshige/Objects/GeoSplash.h" +#include "Kaneshige/Objects/GeoStartLine.h" +#include "Kaneshige/Objects/GeoTideSensor.h" +#include "Kaneshige/Objects/GeoTruck.h" +#include "Kaneshige/Objects/GeoVision.h" +#include "Kaneshige/Objects/GeoWater.h" +#include "Sato/GeographyObj.h" +#include "Sato/Objects/GeoItemBox.h" +#include "Sato/Objects/GeoJumpNarrow.h" +#include "Sato/Objects/GeoRFlower.h" +#include "Sato/Objects/GeoTree.h" +#include "Sato/StringObj.h" +#include "Shiraiwa/Balloon.h" +#include "Shiraiwa/JugemHeadItem.h" +#include "Shiraiwa/JugemItem.h" +#include "Shiraiwa/JugemMain.h" +#include "Shiraiwa/JugemRodItem.h" +#include "Shiraiwa/LensFlare.h" +//#include "Shiraiwa/MapObjDossun.h" +//#include "Shiraiwa/MapObjPoihana.h" +//#include "Shiraiwa/MapObjWanwan.h" +#include "Shiraiwa/Objects/MapObjAward.h" +#include "Shiraiwa/Objects/MapObjPool.h" +#include "Sato/GeographyObjMgr.h" + +#define GEO_OBJ_NEW(GeoClassName) \ +template<> GeoClassName *GeographyObj::New(const CrsData::SObject &sObject) { \ + return new GeoClassName(sObject); \ +} + +#define GEO_OBJ_NEW_S(GeoClassName) \ +template<> GeoClassName *GeographyObj::NewS(const CrsData::SObject &sObject) { \ + return new GeoClassName(); \ +} + +#define EX_GEO_OBJ_NEW(ExGeoClassName) \ +template<> ExGeoClassName *ExGeographyObj::ExNew(const CrsData::SObject &sObject) { \ + return new ExGeoClassName(sObject); \ +} + +#pragma region GeoObj Definitions + +GEO_OBJ_NEW_S(GeoItemBox); +GEO_OBJ_NEW_S(GeoDoubleItemBox); +GEO_OBJ_NEW(GeoF_ItemBox); +// GEO_OBJ_NEW_S(GeoStartLine); +GEO_OBJ_NEW(GeoMarioTree1); +GEO_OBJ_NEW(GeoMarioKinoko1); +// GEO_OBJ_NEW(GeoMarioFlower1); +// GEO_OBJ_NEW(TMapObjDossun); +GEO_OBJ_NEW(GeoNormCar); +GEO_OBJ_NEW_S(GeoCarShadow); +GEO_OBJ_NEW_S(GeoBombShadow); +GEO_OBJ_NEW_S(GeoKinoShadow); +GEO_OBJ_NEW_S(GeoHanaShadow); +GEO_OBJ_NEW_S(GeoHanaBodyShadow); +GEO_OBJ_NEW(GeoTruck); +GEO_OBJ_NEW(GeoBus); +GEO_OBJ_NEW(GeoBombCar); +GEO_OBJ_NEW(GeoKinoCar); +GEO_OBJ_NEW(GeoKuriCar); +GEO_OBJ_NEW(GeoItemCar); +GEO_OBJ_NEW(GeoHanaCar); +GEO_OBJ_NEW_S(GeoHanaBody); +GEO_OBJ_NEW_S(TJugem); +GEO_OBJ_NEW_S(TJugemVoidRod); +GEO_OBJ_NEW_S(TJugemHeadHear); +GEO_OBJ_NEW_S(TJugemRodBoard); +GEO_OBJ_NEW_S(TJugemRodBoard2); +GEO_OBJ_NEW_S(TJugemRodBoardRev); +GEO_OBJ_NEW_S(TJugemRodSignal); +GEO_OBJ_NEW_S(TJugemRodPukuPuku); +GEO_OBJ_NEW_S(TJugemFlag); +GEO_OBJ_NEW_S(TJugemHeadLamp); +GEO_OBJ_NEW(GeoSignal); +GEO_OBJ_NEW(GeoCannon); +// GEO_OBJ_NEW(TMapObjWanwan); +// GEO_OBJ_NEW_S(TMapObjWanwanChain); +// GEO_OBJ_NEW_S(TMapObjWanwanPile); +// GEO_OBJ_NEW(TMapObjSkyShip); +// GEO_OBJ_NEW_S(TMapObjDonkyRock); +// GEO_OBJ_NEW_S(TMapObjDonkyTree); +GEO_OBJ_NEW(GeoDkCloud); +GEO_OBJ_NEW_S(GeoWaterUp); +GEO_OBJ_NEW_S(GeoWaterUp2); +GEO_OBJ_NEW(GeoWater); +// GEO_OBJ_NEW(TMapObjFireBar); +GEO_OBJ_NEW(GeoVision); +// GEO_OBJ_NEW(TMapObjPoihana); +// GEO_OBJ_NEW(TMapObjWall); +// GEO_OBJ_NEW_S(TSMAButterfly); +// GEO_OBJ_NEW_S(TSMADonkyBird); +// GEO_OBJ_NEW_S(TSMAKamome); +// GEO_OBJ_NEW(TMapObjGeyser); +// GEO_OBJ_NEW(TMapObjGeyserSearch); +// GEO_OBJ_NEW_S(TTestStrBarrel); +// GEO_OBJ_NEW_S(TTestStrItem); +// GEO_OBJ_NEW(TMapObjPeachTree); +// GEO_OBJ_NEW(TMapObjSnowRock); +// GEO_OBJ_NEW(TTestRollObj); +// GEO_OBJ_NEW(TMapObjFountain); +// GEO_OBJ_NEW(TMapObjHeyho); +// GEO_OBJ_NEW_S(TMapObjSubHeyho); +// GEO_OBJ_NEW(TMapObjSanbo); +// GEO_OBJ_NEW(TMapObjWlArrow); +// GEO_OBJ_NEW(TMapObjSnowMan); +// GEO_OBJ_NEW(TMapObjIceBlock); +// GEO_OBJ_NEW(TMapObjNoMove); +GEO_OBJ_NEW(GeoKuribo); +// GEO_OBJ_NEW(TMapObjSun); +// GEO_OBJ_NEW(TMapObjBubble); +// GEO_OBJ_NEW(TMapObjDesun); +// GEO_OBJ_NEW(TMapObjSandPillar); +// GEO_OBJ_NEW(TMapObjFerriswheel); +// GEO_OBJ_NEW(TMapObjMoveItemBoxLimit); +GEO_OBJ_NEW_S(GeoShine); +GEO_OBJ_NEW_S(TBalloon); +// GEO_OBJ_NEW(TMapObjJetCoasterHead); +// GEO_OBJ_NEW_S(TMapObjJetCoasterBody); +GEO_OBJ_NEW(TMapObjPool); +// GEO_OBJ_NEW(TMapObjDeBalloon); +// GEO_OBJ_NEW(TMapObjJetKpFire); +// GEO_OBJ_NEW_S(TMapObjSanboHead); +// GEO_OBJ_NEW_S(TMapObjSanboBody); +// GEO_OBJ_NEW(TMapObjRollTable); +// GEO_OBJ_NEW(TMapObjMoveItemBox); +// GEO_OBJ_NEW(TMapObjNossie); +// GEO_OBJ_NEW(TMapObjMareA); +// GEO_OBJ_NEW(TMapObjMareB); +// GEO_OBJ_NEW(TMapObjMareC); +// GEO_OBJ_NEW(TMapObjMonteA); +// GEO_OBJ_NEW(TMapObjMonteB); +// GEO_OBJ_NEW(TMapObjMonteC); +// GEO_OBJ_NEW(TMapObjMareW_A); +// GEO_OBJ_NEW(TMapObjMareW_B); +// GEO_OBJ_NEW(TMapObjMareW_C); +// GEO_OBJ_NEW(TMapObjMareM_A); +// GEO_OBJ_NEW(TMapObjMeteor); +// GEO_OBJ_NEW(TMapObjUkeleleMonte); +// GEO_OBJ_NEW(TMapObjDanceMonteA); +// GEO_OBJ_NEW(TMapObjDanceMonteB); +GEO_OBJ_NEW(TMapObjAwardItemBox); +// GEO_OBJ_NEW_S(TMapObjAwardCupKinoko); +// GEO_OBJ_NEW_S(TMapObjAwardCupFlower); +// GEO_OBJ_NEW_S(TMapObjAwardCupStar); +// GEO_OBJ_NEW_S(TMapObjAwardCupSpecial); +// GEO_OBJ_NEW_S(TMapObjAwardCupReverse); +// GEO_OBJ_NEW_S(TMapObjAwardCupAllTour); +GEO_OBJ_NEW(TMapObjAntLion); +// GEO_OBJ_NEW(TMapObjPakkun); +GEO_OBJ_NEW(GeoKinojii); +// GEO_OBJ_NEW(TMapObjDinoTree); +// GEO_OBJ_NEW(TMapObjDemoFountain); +// GEO_OBJ_NEW(TMapObjKpGear); +// GEO_OBJ_NEW(TMapObjKpFireBar); +// GEO_OBJ_NEW(TMapObjSwimNossie); +// GEO_OBJ_NEW(TMapObjPtera); +// GEO_OBJ_NEW(TMapObjPeachTree2); +// GEO_OBJ_NEW(TMapObjYoshiHeli); +// GEO_OBJ_NEW(TMapObjDesertTree); +// GEO_OBJ_NEW(TMapObjWluSearchLight); +// GEO_OBJ_NEW(TMapObjVentilator); +// GEO_OBJ_NEW_S(TShineArrow); +// GEO_OBJ_NEW(TMapObjUFO); +// GEO_OBJ_NEW(TMapObjMashBalloon); +// GEO_OBJ_NEW(TMapObjPathYoshiHeli); +// GEO_OBJ_NEW(TMapObjFireBall); +// GEO_OBJ_NEW(TMapObjUFO); +GEO_OBJ_NEW_S(GeoWaterDown); +GEO_OBJ_NEW_S(GeoWaterMiddleD); +// GEO_OBJ_NEW(TMapObjDonkyRockGen); +// GEO_OBJ_NEW(TMapObjFireCircle); +GEO_OBJ_NEW(GeoItemGen); +// GEO_OBJ_NEW(TSMAButterflyGen); +// GEO_OBJ_NEW(TSMADonkyBirdGen); +// GEO_OBJ_NEW(TSMABoidBirdManager); +// GEO_OBJ_NEW(TTestString); +GEO_OBJ_NEW_S(TBalloonString); +GEO_OBJ_NEW(TLensFlare); +// GEO_OBJ_NEW(TDistSnow); +GEO_OBJ_NEW_S(TBalloonManager); +GEO_OBJ_NEW(GeoAirJet); +// GEO_OBJ_NEW_S(TMapObjNossieColHead); +// GEO_OBJ_NEW_S(TMapObjNossieColFootFront); +// GEO_OBJ_NEW_S(TMapObjNossieColFootRear); +// GEO_OBJ_NEW(TMapObjNossieColBody); +GEO_OBJ_NEW(GeoSplash); +GEO_OBJ_NEW(GeoTideSensor); +GEO_OBJ_NEW(GeoPuller); +GEO_OBJ_NEW(GeoShimmer); +// GEO_OBJ_NEW_S(TMapObjPakkunColHead); +GEO_OBJ_NEW(GeoSoundGen); +GEO_OBJ_NEW(GeoRabbitMark); +EX_GEO_OBJ_NEW(GeoJumpNarrow); +//EX_GEO_OBJ_NEW(StringBridge); + + +#pragma endregion +// GeoObj Definitions From 7bf7e18a119a32b2358acf1133176cfce2529f51 Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 16:29:40 +1000 Subject: [PATCH 02/29] GeoObjMgr - Add GeoStartLine --- include/Kaneshige/Objects/GeoStartLine.h | 5 ++--- src/Kaneshige/GeoStartLine.cpp | 4 ++-- src/Sato/GeographyObjMgr.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/Kaneshige/Objects/GeoStartLine.h b/include/Kaneshige/Objects/GeoStartLine.h index fe782f7c..87e6168a 100644 --- a/include/Kaneshige/Objects/GeoStartLine.h +++ b/include/Kaneshige/Objects/GeoStartLine.h @@ -3,9 +3,8 @@ #include "Sato/GeographyObj.h" -class GeoStartLine : public GeographyObj -{ - // Global +class GeoStartLine : public GeographyObj { +public: GeoStartLine(); // 0x801b4860 virtual ~GeoStartLine() {} // 0x801b4bd0 virtual void reset(); // 0x801b49c8 diff --git a/src/Kaneshige/GeoStartLine.cpp b/src/Kaneshige/GeoStartLine.cpp index cd950f8b..538136fa 100644 --- a/src/Kaneshige/GeoStartLine.cpp +++ b/src/Kaneshige/GeoStartLine.cpp @@ -54,6 +54,6 @@ void GeoStartLine::createColModel(J3DModelData *) { } const char *GeoStartLine::getBmdFileName() { static const char *cTreeBmdName = "/Objects/StartLine.bmd"; return cTreeBmdName; - } +} - void GeoStartLine::calc() {} +void GeoStartLine::calc() {} diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 52d1954e..a56fb735 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -66,7 +66,7 @@ template<> ExGeoClassName *ExGeographyObj::ExNew(const CrsData:: GEO_OBJ_NEW_S(GeoItemBox); GEO_OBJ_NEW_S(GeoDoubleItemBox); GEO_OBJ_NEW(GeoF_ItemBox); -// GEO_OBJ_NEW_S(GeoStartLine); +GEO_OBJ_NEW_S(GeoStartLine); GEO_OBJ_NEW(GeoMarioTree1); GEO_OBJ_NEW(GeoMarioKinoko1); // GEO_OBJ_NEW(GeoMarioFlower1); From 8f8680830f47e17a86f2754b82fe0d68d8b6d16f Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 16:32:35 +1000 Subject: [PATCH 03/29] GeoObjMgr - Add GeoMarioFlower1 --- include/Sato/Objects/GeoRFlower.h | 1 + src/Sato/GeographyObjMgr.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Sato/Objects/GeoRFlower.h b/include/Sato/Objects/GeoRFlower.h index 67309e5e..68e739de 100644 --- a/include/Sato/Objects/GeoRFlower.h +++ b/include/Sato/Objects/GeoRFlower.h @@ -16,6 +16,7 @@ class GeoRFlower : public GeographyObj { // Autogenerated class GeoMarioFlower1 : public GeographyObj { +public: GeoMarioFlower1(const CrsData::SObject &); ~GeoMarioFlower1() {} void reset(); diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index a56fb735..633dc0c2 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -69,7 +69,7 @@ GEO_OBJ_NEW(GeoF_ItemBox); GEO_OBJ_NEW_S(GeoStartLine); GEO_OBJ_NEW(GeoMarioTree1); GEO_OBJ_NEW(GeoMarioKinoko1); -// GEO_OBJ_NEW(GeoMarioFlower1); +GEO_OBJ_NEW(GeoMarioFlower1); // GEO_OBJ_NEW(TMapObjDossun); GEO_OBJ_NEW(GeoNormCar); GEO_OBJ_NEW_S(GeoCarShadow); From ab5cced8706b9c5f5aa12d9a07372f3ec0388c95 Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 16:50:42 +1000 Subject: [PATCH 04/29] Rename CrsData's `pathID` property to `mPathID` - discovered that `TMapObjDonkyRock::start()` has a `JUT_ASSERT` specifically referencing this property with the name `mPathID`. Renaming existing implementations to match this. --- include/Kaneshige/Course/CrsData.h | 2 +- include/Sato/GeographyObj.h | 2 +- src/Kaneshige/GeoCar.cpp | 22 +++++++++++----------- src/Kaneshige/GeoKuribo.cpp | 12 ++++++------ src/Kaneshige/GeoRabbitMark.cpp | 6 +++--- src/Sato/GeoObjPathMove.cpp | 4 ++-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/Kaneshige/Course/CrsData.h b/include/Kaneshige/Course/CrsData.h index 91f7ba15..15166f6e 100644 --- a/include/Kaneshige/Course/CrsData.h +++ b/include/Kaneshige/Course/CrsData.h @@ -183,7 +183,7 @@ class CrsData JGeometry::TVec3 zNorm; // 18 JGeometry::TVec3 yNorm; // 1e u16 objID; - u16 pathID; // 26 + u16 mPathID; // 26 u16 _28; // u16 pointIdx; // 2a struct { diff --git a/include/Sato/GeographyObj.h b/include/Sato/GeographyObj.h index 0f1db62b..6ebae854 100644 --- a/include/Sato/GeographyObj.h +++ b/include/Sato/GeographyObj.h @@ -118,7 +118,7 @@ class GeographyObj void setItemColReaction(u8 p1, u8 p2) { mReaction.setFlg(p1, p2); } - bool IsPathMove() const { return mObjData->pathID != 0xffff; } + bool IsPathMove() const { return mObjData->mPathID != 0xffff; } template static T *New(const CrsData::SObject &object) { return new T(object); } diff --git a/src/Kaneshige/GeoCar.cpp b/src/Kaneshige/GeoCar.cpp index eb13a0fd..a735b935 100644 --- a/src/Kaneshige/GeoCar.cpp +++ b/src/Kaneshige/GeoCar.cpp @@ -288,7 +288,7 @@ void GeoCar::reset() { void GeoCar::setTargetPoint(u16 targetId) { CrsData *crsData = RaceMgr::getManager()->getCourse()->getCrsData(); u16 pointId = targetId; // probably fake - CrsData::PathData *pathData = crsData->getPathData(mObjData->pathID); + CrsData::PathData *pathData = crsData->getPathData(mObjData->mPathID); if (pointId == 0xffff) { pointId = 0; @@ -300,10 +300,10 @@ void GeoCar::setTargetPoint(u16 targetId) { u16 nextPointId = pointId + 1; mPointIdx = nextPointId; - mBasePos = crsData->getPointData(mObjData->pathID, pointId)->pos; + mBasePos = crsData->getPointData(mObjData->mPathID, pointId)->pos; JGeometry::TVec3f v; - v = crsData->getPointData(mObjData->pathID, nextPointId)->pos; + v = crsData->getPointData(mObjData->mPathID, nextPointId)->pos; CrsGround ground(nullptr); ground.search(mBasePos); @@ -488,10 +488,10 @@ void GeoCar::MoveExec() { Observer_FindAndExec(GeoCar, 6); } void GeoCar::getTargetPosition(JGeometry::TVec3f *out) { CrsData *crsData = RaceMgr::getManager()->getCourse()->getCrsData(); - CrsData::PointData *point = crsData->getPointData(mObjData->pathID, mPointIdx); + CrsData::PointData *point = crsData->getPointData(mObjData->mPathID, mPointIdx); out->set(point->pos); if (mPointIdx != 0) { - CrsData::PointData *prevPoint = crsData->getPointData(mObjData->pathID, mPointIdx - 1); + CrsData::PointData *prevPoint = crsData->getPointData(mObjData->mPathID, mPointIdx - 1); JGeometry::TVec3f up(0.0f, 1.0f, 0.0f); JGeometry::TVec3f dist; dist.sub(point->pos, prevPoint->pos); @@ -522,7 +522,7 @@ void GeoCar::setAllObjectCollision(bool doSet) { u16 GeoCar::getPathID() { u16 ret = 0xffff; if (mObjData) - ret = mObjData->pathID; + ret = mObjData->mPathID; return ret; } @@ -630,12 +630,12 @@ void GeoCar::checkTargetPoint() { CrsData *crsData = RaceMgr::getManager()->getCourse()->getCrsData(); JGeometry::TVec3f pointPos; - pointPos.set(crsData->getPointData(mObjData->pathID, mPointIdx)->pos); + pointPos.set(crsData->getPointData(mObjData->mPathID, mPointIdx)->pos); JGeometry::TVec3f dist; dist.sub(pointPos, mPos); if (dist.length() <= mTargetRadius) { - CrsData::PathData *path = RCMGetCourse()->getCrsData()->getPathData(mObjData->pathID); + CrsData::PathData *path = RCMGetCourse()->getCrsData()->getPathData(mObjData->mPathID); u16 pointCount = path->pointCount; mPointIdx++; if (mPointIdx < pointCount) @@ -646,13 +646,13 @@ void GeoCar::checkTargetPoint() { if (path->isClosed()) return; - CrsData::PointData *lastPoint = RCMGetCourse()->getCrsData()->getPointData(mObjData->pathID, pointCount - 1); + CrsData::PointData *lastPoint = RCMGetCourse()->getCrsData()->getPointData(mObjData->mPathID, pointCount - 1); if (lastPoint->linkPoint) { u16 linkPointId = 0xffff; for (u16 i = 0; i < (u16)pointCount; i++) { - //CrsData::PointData *point = RCMGetCourse()->getCrsData()->getPointData(mObjData->pathID, i); - if (RCMGetCourse()->getCrsData()->getPointData(mObjData->pathID, i)->linkPoint == lastPoint->linkPoint) { + //CrsData::PointData *point = RCMGetCourse()->getCrsData()->getPointData(mObjData->mPathID, i); + if (RCMGetCourse()->getCrsData()->getPointData(mObjData->mPathID, i)->linkPoint == lastPoint->linkPoint) { linkPointId = i; break; } diff --git a/src/Kaneshige/GeoKuribo.cpp b/src/Kaneshige/GeoKuribo.cpp index 356ce592..841d709f 100644 --- a/src/Kaneshige/GeoKuribo.cpp +++ b/src/Kaneshige/GeoKuribo.cpp @@ -125,10 +125,10 @@ void GeoKuribo::reset() { _21c = 0.0; resetAnimation(); #line 326 - JUT_ASSERT_MSG(mObjData->pathID != 0xffff, "UNLINK PATH"); + JUT_ASSERT_MSG(mObjData->mPathID != 0xffff, "UNLINK PATH"); CrsData *crsData = RaceMgr::getManager()->getCourse()->getCrsData(); - mPos.set(crsData->getPointData(mObjData->pathID, 0)->pos); + mPos.set(crsData->getPointData(mObjData->mPathID, 0)->pos); mGround.search(mPos); mPos.y = mGround.getHeight(); mGround.getNormal(&mUpDir); @@ -151,7 +151,7 @@ void GeoKuribo::resetWalkDirection(s16 pointID) { CrsData *crsData = RaceMgr::getManager()->getCourse()->getCrsData(); s16 startID = pointID; // fakematch? - CrsData::PathData *pathData = crsData->getPathData(mObjData->pathID); + CrsData::PathData *pathData = crsData->getPathData(mObjData->mPathID); u16 pointCount = (u16)pathData->pointCount; if (tstKuriboFlagDecPoint()) { @@ -163,7 +163,7 @@ void GeoKuribo::resetWalkDirection(s16 pointID) { startID++; } mPointID = startID; - CrsData::PointData *pointData = crsData->getPointData(mObjData->pathID, mPointID); + CrsData::PointData *pointData = crsData->getPointData(mObjData->mPathID, mPointID); JGeometry::TVec3f vel; vel.sub(pointData->pos, mPos); @@ -332,7 +332,7 @@ void GeoKuribo::initFuncWalk() { } void GeoKuribo::doFuncWalk() { - CrsData::PointData *pointData = RaceMgr::getManager()->getCourse()->getCrsData()->getPointData(mObjData->pathID, mPointID); + CrsData::PointData *pointData = RaceMgr::getManager()->getCourse()->getCrsData()->getPointData(mObjData->mPathID, mPointID); u8 anm_no = GeographyObj::getAnmCtrl()->AnmController::getNowTransNo(); J3DFrameCtrl *ctrl = GeographyObj::getAnmCtrl()->AnmController::getFrameCtrl(anm_no); @@ -384,7 +384,7 @@ void GeoKuribo::doFuncWalk() { vel2.sub(pointData->pos, mPos); if (vel2.squared() < (sPointR*sPointR)) { - CrsData::PathData *pathData = RCMGetCourse()->getCrsData()->getPathData(mObjData->pathID); + CrsData::PathData *pathData = RCMGetCourse()->getCrsData()->getPathData(mObjData->mPathID); s16 pointId = pathData->pointCount; u8 anm_no = GeographyObj::getAnmCtrl()->AnmController::getNowTransNo(); J3DFrameCtrl *ctrl = GeographyObj::getAnmCtrl()->AnmController::getFrameCtrl(anm_no); diff --git a/src/Kaneshige/GeoRabbitMark.cpp b/src/Kaneshige/GeoRabbitMark.cpp index 44780fda..75a49e3f 100644 --- a/src/Kaneshige/GeoRabbitMark.cpp +++ b/src/Kaneshige/GeoRabbitMark.cpp @@ -142,7 +142,7 @@ void GeoRabbitMark::reset() { _1c0 = 0; #line 476 - JUT_ASSERT_MSG(mObjData->pathID != 0xffff, "UNLINK PATH") + JUT_ASSERT_MSG(mObjData->mPathID != 0xffff, "UNLINK PATH") bool initialized = false; if (mState == 0) initialized = true; @@ -152,9 +152,9 @@ void GeoRabbitMark::reset() { void GeoRabbitMark::resetPose(bool initialized) { mVel.zero(); if (initialized) { - CrsData::PathData *pathData = RaceMgr::getManager()->getCourse()->getCrsData()->getPathData(mObjData->pathID); + CrsData::PathData *pathData = RaceMgr::getManager()->getCourse()->getCrsData()->getPathData(mObjData->mPathID); u16 pointId = getGeoRnd()->getRandom() % pathData->pointCount; - CrsData::PointData *pointData = RaceMgr::getManager()->getCourse()->getCrsData()->getPointData(mObjData->pathID, pointId); + CrsData::PointData *pointData = RaceMgr::getManager()->getCourse()->getCrsData()->getPointData(mObjData->mPathID, pointId); mPos.set(pointData->pos); } else { diff --git a/src/Sato/GeoObjPathMove.cpp b/src/Sato/GeoObjPathMove.cpp index 280a8f2e..da67fb44 100644 --- a/src/Sato/GeoObjPathMove.cpp +++ b/src/Sato/GeoObjPathMove.cpp @@ -68,7 +68,7 @@ void GeoObjPathMove::nodeProc() { } CrsData::PathData *GeoObjPathMove::getPathData() { - return RCMGetCourse()->getCrsData()->getPathData(mObj.pathID); + return RCMGetCourse()->getCrsData()->getPathData(mObj.mPathID); } u16 GeoObjPathMove::getMaxPathNodeNum() { @@ -76,7 +76,7 @@ u16 GeoObjPathMove::getMaxPathNodeNum() { } void GeoObjPathMove::getPathPos(JGeometry::TVec3f *pos, u16 pointID) { - *pos = RCMGetCourse()->getCrsData()->getPointData(mObj.pathID, pointID)->pos; + *pos = RCMGetCourse()->getCrsData()->getPointData(mObj.mPathID, pointID)->pos; } void GeoObjPathMoveWaveY::initPath(stRandom *rand, JGeometry::TVec3f *pos, const f32 &p3) { From de2013253f3fb9687ef3e66ad8d23289a2a25dee Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 18:42:09 +1000 Subject: [PATCH 05/29] GeoObjMgr - Implement majority of TMapObjDonkyRock. Note there are a few minor register mismatches, but the majority of the code is a match. --- include/Shiraiwa/Objects/MapObjDonkyRock.h | 87 +++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/MapObjDonkyRock.cpp | 360 +++++++++++++++++++++ 3 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjDonkyRock.h diff --git a/include/Shiraiwa/Objects/MapObjDonkyRock.h b/include/Shiraiwa/Objects/MapObjDonkyRock.h new file mode 100644 index 00000000..675438a5 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjDonkyRock.h @@ -0,0 +1,87 @@ +#ifndef MAPOBJDONKYROCK_H +#define MAPOBJDONKYROCK_H + +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JKernel/JKRDisposer.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjDonkyRock; + +class TDonkyRockSupervisor : public GeoObjSupervisor { +public: + TDonkyRockSupervisor(); // 0x8029c034 + virtual ~TDonkyRockSupervisor(); // 0x8029c120 + virtual void reset() { return; } // 0x8029c1c0 + virtual void calc() { return; } // 0x8029c1c4 + virtual void thunderDownAll(); // 0x8029c0d8 + void entry(TMapObjDonkyRock *); // 0x8029c0b0 + +private: + JSUList mList; +}; + +class TMapObjDonkyRock : public TMapObjHioNode, public StateObserver, JKRDisposer { // Autogenerated +public: + TMapObjDonkyRock(); // 0x8029aac4 + virtual ~TMapObjDonkyRock(); // 0x8029abc8 + virtual void MoveExec(); // 0x8029b030 + virtual void InitExec(); // 0x8029afc4 + virtual void loadAnimation(); // 0x8029aefc + virtual void createColModel(J3DModelData *); // 0x8029ad5c + virtual void reset(); // 0x8029aca8 + virtual void calc(); // 0x8029b09c + virtual const char *getBmdFileName(); // 0x8029ad88 + virtual const char *getShadowBmdFileName(); // 0x8029adb0 + virtual void createModel(JKRSolidHeap *, u32); // 0x8029af00 + virtual TDonkyRockSupervisor *getSupervisor() { return sSupervisor; } // 0x8029abc0 + virtual void doKartColCallBack(int); // 0x8029bf4c + void start(); // 0x8029add8 + void setObjData(const CrsData::SObject *); // 0x8029af30 + void initFunc_Wait(); // 0x8029b0d4 + void doFunc_Wait(); // 0x8029b0fc + void initFunc_Fall(); // 0x8029b100 + void setStartVel(); // 0x8029b164 + void doFunc_Fall(); // 0x8029b4c0 + void move_FallDown(JGeometry::TVec3f &); // 0x8029b5d0 + void getReflect(JGeometry::TVec3f &, JGeometry::TVec3f &); // 0x8029bbd4 + void getNodePosition(JGeometry::TVec3f *, u16); // 0x8029bdd8 + void initFunc_Break(); // 0x8029be44 + void doFunc_Break(); // 0x8029bf24 + + static StateFuncSet sTable[3]; // 0x803a4ba0 + static f32 sReflectRate; // 0x804151c0 + static f32 sFricRate; // 0x804151c4 + static f32 sGravity; // 0x804151c8 + static f32 sMaxSpeed; // 0x804151cc + static f32 sRotSpeed; // 0x804151d0 + static f32 sKartDownScale; // 0x804151d4 + static TDonkyRockSupervisor *sSupervisor; // 0x80416e50 + + + // Inline/Unused + //void JSULink::~JSULink(); + //void JSUList::~JSUList(); + //void sRockRadius; + +public: + JSULink _170; // 0x170 + f32 _180; // 0x180 + JGeometry::TVec3f _184; // 0x184 + f32 _190; // 0x190 + u16 _194; // 0x194 + u16 _196; // 0x196 - Padding? + JGeometry::TVec3f _198; // 0x198 + GameAudio::RockSoundMgr *mRockSoundMgr; // 0x1a4 + const CrsData::SObject *mGenObjData; // 0x1a8 - setObjData implies this should be const... + CrsGround *mCrsGround; // 0x1ac +}; // 0x1b0 + +// Outside class members + +#endif // MAPOBJDONKYROCK_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 633dc0c2..cf488224 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -43,6 +43,7 @@ //#include "Shiraiwa/MapObjPoihana.h" //#include "Shiraiwa/MapObjWanwan.h" #include "Shiraiwa/Objects/MapObjAward.h" +#include "Shiraiwa/Objects/MapObjDonkyRock.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Sato/GeographyObjMgr.h" @@ -101,7 +102,7 @@ GEO_OBJ_NEW(GeoCannon); // GEO_OBJ_NEW_S(TMapObjWanwanChain); // GEO_OBJ_NEW_S(TMapObjWanwanPile); // GEO_OBJ_NEW(TMapObjSkyShip); -// GEO_OBJ_NEW_S(TMapObjDonkyRock); +GEO_OBJ_NEW_S(TMapObjDonkyRock); // GEO_OBJ_NEW_S(TMapObjDonkyTree); GEO_OBJ_NEW(GeoDkCloud); GEO_OBJ_NEW_S(GeoWaterUp); diff --git a/src/Shiraiwa/MapObjDonkyRock.cpp b/src/Shiraiwa/MapObjDonkyRock.cpp index e69de29b..7816bd89 100644 --- a/src/Shiraiwa/MapObjDonkyRock.cpp +++ b/src/Shiraiwa/MapObjDonkyRock.cpp @@ -0,0 +1,360 @@ +#include "Inagaki/GameAudioMain.h" +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/JAudio/System/JASKernel.h" +#include "JSystem/JGeometry/Quat.h" +#include "JSystem/JGeometry/Util.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JSupport/JSUList.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/Course/CrsGround.h" +#include "Kaneshige/RaceMgr.h" +#include "Sato/ItemThunder.h" +#include "Sato/JPEffectMgr.h" +#include "Sato/ObjCollision.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Objects/MapObjDonkyRock.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "dolphin/mtx.h" +#include "types.h" +#include + +StateObserver::StateFuncSet TMapObjDonkyRock::sTable[3] = { + { 0, &TMapObjDonkyRock::initFunc_Wait, &TMapObjDonkyRock::doFunc_Wait }, + { 1, &TMapObjDonkyRock::initFunc_Fall, &TMapObjDonkyRock::doFunc_Fall }, + { 2, &TMapObjDonkyRock::initFunc_Break, &TMapObjDonkyRock::doFunc_Break }, +}; +TDonkyRockSupervisor *TMapObjDonkyRock::sSupervisor; +f32 TMapObjDonkyRock::sReflectRate = 0.55f; +f32 TMapObjDonkyRock::sFricRate = 0.99f; +f32 TMapObjDonkyRock::sGravity = -1.0f; +f32 TMapObjDonkyRock::sMaxSpeed = 80.0f; +f32 TMapObjDonkyRock::sRotSpeed = 0.0031f; +f32 TMapObjDonkyRock::sKartDownScale = 0.3f; + +TMapObjDonkyRock::TMapObjDonkyRock() : TMapObjHioNode(0x1197), StateObserver(), _170(this) { + mGenObjData = nullptr; + setObjFlagSimpleDraw(); + mCrsGround = new CrsGround(RaceMgr::getManager()->getCourse()); + if (getSupervisor() == nullptr) { + sSupervisor = new TDonkyRockSupervisor(); + } + sSupervisor->entry(this); +} + +TMapObjDonkyRock::~TMapObjDonkyRock() { + delete mCrsGround; + sSupervisor = nullptr; +} + +void TMapObjDonkyRock::reset() { + const CrsData::SObject *genObjData; + ShadowModel *shadowModel; + + GeographyObj::resetObject(); + genObjData = mGenObjData; + mScale.set(genObjData->scale); + mBounds[0]->setScale(mScale); + _58 = 0xb; + _184.zero(); + _190 = 0.0f; + _194 = 0; + StateObserver::ResetState(); + clrObjFlagCheckGeoHitting(); + setObjFlagHidding(); + shadowModel = mShadowMdl; + if (shadowModel != nullptr) { + shadowModel->clrVisibleAll(); + } + return; +} + +void TMapObjDonkyRock::createColModel(J3DModelData *modelData) { + createBoundsSphere(modelData); +} + +const char *TMapObjDonkyRock::getBmdFileName() { + static const char *cBmdName = "/Objects/DonkyRock1.bmd"; + return cBmdName; +} + +const char *TMapObjDonkyRock::getShadowBmdFileName() { + static const char *cShadowBmdName = "/Objects/DonkyRock1Shadow.bmd"; + return cShadowBmdName; +} + +// FIX: Register mismatch for `mGenObjData->position.y + _180` +void TMapObjDonkyRock::start() { + #line 166 + JUT_ASSERT(mGenObjData != 0); + #line 168 + JUT_ASSERT(mGenObjData->mPathID != 0xffff); + + mPos.set(mGenObjData->position.x, mGenObjData->position.y + _180, mGenObjData->position.z); + + setObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + clrObjFlagHidding(); + if (mShadowMdl != nullptr) { + mShadowMdl->setVisibleAll(); + } + moveShadowModel(); + _58 = 0xb; + setState(1); +} + +void TMapObjDonkyRock::loadAnimation() {} + +void TMapObjDonkyRock::createModel(JKRSolidHeap *heap, u32 param_2) { + mModel.createModel(heap, param_2, 0); +} + +void TMapObjDonkyRock::setObjData(const CrsData::SObject *sObject) { + mGenObjData = sObject; + _180 = mGenObjData->scale.y * 300.0f; + _196 = RaceMgr::getManager()->getCourse()->getCrsData()-> + getPathData(mGenObjData->mPathID)->pointCount; + mRockSoundMgr = new GameAudio::RockSoundMgr(&mPos, sObject->scale.y, nullptr); + setStartVel(); +} + +void TMapObjDonkyRock::calc() { + ExecuteState(); + mRockSoundMgr->frameWork(); +} + +void TMapObjDonkyRock::initFunc_Wait() { + setObjFlagHidding(); + if (mShadowMdl == nullptr) { + return; + } + mShadowMdl->clrVisibleAll(); +} + +void TMapObjDonkyRock::doFunc_Wait() {} + +void TMapObjDonkyRock::initFunc_Fall() { + mVel.set(_198); + _184.zero(); + _190 = 0.0f; + _194 = 1; + clrObjFlagHidding(); + setAllCheckKartHitFlag(); + if (mShadowMdl == nullptr) { + return; + } + mShadowMdl->setVisibleAll(); +} + +// FIX: Register mismatch and missing `fmr` call around `setRotate` call. +void TMapObjDonkyRock::setStartVel() { + static JGeometry::TVec3f axisY(0.0f, 1.0f, 0.0f); + + f32 speed = mGenObjData->mParam3; + + if (speed > 0.0f) { + JGeometry::TVec3f nodePos; + getNodePosition(&nodePos, 1); + + _198.sub(nodePos, mGenObjData->position); + _198.y = 0.0f; + _198.normalize(); + + JGeometry::TVec3f axis; + axis.cross(_198, axisY); + axis.normalize(); + + JGeometry::TQuat4f rot; + rot.setRotate(axis, MTXDegToRad((f32)mGenObjData->mParam4)); + rot.transform(_198); + + _198.scale(speed); + } else { + _198.zero(); + } +} + +void TMapObjDonkyRock::doFunc_Fall() { + u16 nodeIdx = _194; + if (nodeIdx >= _196) { + nodeIdx = _196 - 1; + } + + JGeometry::TVec3f pos; + getNodePosition(&pos, nodeIdx); + move_FallDown(pos); + + GeographyObj::moveShadowModel(); + pos.sub(mPos); + + f32 sq = pos.squaredZX(); + if (pos.y > 0.0f || sq < (_180 * _180)) { + _194++; + } + + if (_194 >= _196) { + setState(2); + } + if (tstItemHitting() != 0) { + // What is 7 in this context? + if (getColItemObj()->getKind() - 7 <= 2 || (getColItemObj()->getKind() == 1)) { + setState(2); + } + } +} + +void TMapObjDonkyRock::move_FallDown(JGeometry::TVec3f ¶m_1) { + JGeometry::TVec3f *mPosCopy; + JGeometry::TVec3f local_a4; + JGeometry::TVec3f local_b0; + JGeometry::TVec3f local_bc; + JGeometry::TVec3f local_c8; + + mVel.add(_184); + if (mVel.squared() > sMaxSpeed * sMaxSpeed) { + mVel.normalize(); + mVel.scale(sMaxSpeed); + } + mPosCopy = &mPos; + mPosCopy->add(mVel); + _184.set(0.0f, sGravity, 0.0f); + mCrsGround->search(*mPosCopy); + + u32 attr = mCrsGround->getAttribute(); + static JGeometry::TVec3f axisY(0.0f, 1.0f, 0.0f); + + if (attr != CrsGround::Attr_10 && mPos.y < _180 + mCrsGround->getHeight()) { + mCrsGround->getNormal(&local_c8); + local_a4.normalize(local_c8); + local_bc.sub(param_1, mPos); + local_bc.normalize(); + PSVECCrossProduct(&local_bc, &local_a4, &local_b0); + local_b0.normalize(); + mPos.y = _180 + mCrsGround->getHeight(); + getReflect(local_a4, local_bc); + } + + local_bc.set(mVel.x, 0.0f, mVel.z); + + if (!local_bc.isZero()) { + local_a4.set(axisY); + local_bc.normalize(); + + PSVECCrossProduct(&local_bc, &local_a4, &local_b0); + local_b0.normalize(); + _190 += (-sRotSpeed * mVel.length()) / mScale.y; + + f32 fVar1; + for (fVar1 = _190; fVar1 < -JGeometry::TUtilf::PI();) { + fVar1 += 2.0f * JGeometry::TUtilf::PI(); + } + + while (fVar1 >= JGeometry::TUtilf::PI()) { + fVar1 -= 2.0f * JGeometry::TUtilf::PI(); + } + + _190 = fVar1; + mRotMtx.setRotate(local_b0, _190); + } +} +// FIX: Register mismatch - probably from squared() function. +void TMapObjDonkyRock::getReflect(JGeometry::TVec3f &normal, JGeometry::TVec3f &direction) { + JGeometry::TVec3f proj; + proj.scale(normal.dot(mVel), normal); + + if (proj.squared() <= (100.0f + sGravity * sGravity)) { + proj.scale(-0.9f); + mVel.add(proj); + mVel.scale(sFricRate); + + mRockSoundMgr->setRollSe(mVel.length()); + } else { + proj.scale(-(1.0f + sReflectRate)); + mVel.add(proj); + + f32 speed = mVel.length(); + + mVel.normalize(); + mVel.x = direction.x; + mVel.z = direction.z; + + mVel.scale(speed); + mRockSoundMgr->setBoundSe(speed); + } +} + +void TMapObjDonkyRock::getNodePosition(JGeometry::TVec3f *param_1, u16 param_2) { + CrsData::PointData *pPVar1 = RCMGetCourse()->getCrsData()->getPointData(mGenObjData->mPathID, param_2); + param_1->set(pPVar1->pos); + param_1->y += _180; +} + +void TMapObjDonkyRock::initFunc_Break() { + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + if (mShadowMdl != nullptr) { + mShadowMdl->clrVisibleAll(); + } + setObjFlagHidding(); + JPABaseEmitter *baseEmitter = JPEffectMgr::getEffectMgr()->createEmt("mk_donkyRock_a", mPos); + baseEmitter->setGlobalScale(mScale); + baseEmitter = JPEffectMgr::getEffectMgr()->createEmt("mk_donkyRock_b", mPos); + baseEmitter->setGlobalScale(mScale); + mRockSoundMgr->setBrokenSe(); +} + +void TMapObjDonkyRock::doFunc_Break() { + setState(0); +} + +void TMapObjDonkyRock::doKartColCallBack(int kartIdx) { + bool changeState = false; + + if (GetKartCtrl()->getKartBody(kartIdx)->mCarStatus & 0x100040004ULL) { + _58 = 11; + changeState = true; + } else if (GetKartCtrl()->getKartBody(kartIdx)->mCarStatus & 0x4000ULL) { + _58 = 11; + + if (RCMGetManager()->getRaceMode() != 1) { + changeState = true; + } + } else if (mScale.y < sKartDownScale) { + _58 = 0; + changeState = true; + } else { + _58 = 11; + } + + if (changeState) { + setState(2); + } +} + +void TMapObjDonkyRock::MoveExec() { + Observer_FindAndExec(TMapObjDonkyRock, 3); +} + +void TMapObjDonkyRock::InitExec() { + Observer_FindAndInit(TMapObjDonkyRock, 3); +} + + +TDonkyRockSupervisor::TDonkyRockSupervisor() { + mList.initiate(); + ItemThunder::entrySuperVisor(this); +} + +TDonkyRockSupervisor::~TDonkyRockSupervisor() {} + +void TDonkyRockSupervisor::entry(TMapObjDonkyRock *tMapObjDonkyRock) { + mList.append(&tMapObjDonkyRock->_170); +} + +void TDonkyRockSupervisor::thunderDownAll() { + for (JSULink *donkyRockItem = mList.getFirst(); donkyRockItem != nullptr; donkyRockItem = donkyRockItem->getNext()) { + donkyRockItem->getObject()->setState(2); + } +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From e8645af310ea4e0bd104d3ea5dee7af13f3a6a92 Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 18:49:48 +1000 Subject: [PATCH 06/29] GeoObjMgr - Implement TMapObjDonkyRockGen. --- include/Shiraiwa/Objects/MapObjDonkyRockGen.h | 26 ++++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/MapObjDonkyRockGen.cpp | 81 +++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjDonkyRockGen.h diff --git a/include/Shiraiwa/Objects/MapObjDonkyRockGen.h b/include/Shiraiwa/Objects/MapObjDonkyRockGen.h new file mode 100644 index 00000000..071061cd --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjDonkyRockGen.h @@ -0,0 +1,26 @@ +#ifndef MAPOBJDONKYROCKGEN_H +#define MAPOBJDONKYROCKGEN_H + +#include "JSystem/J3D/J3DModel.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" +#include "Shiraiwa/Objects/MapObjDonkyRock.h" + +class TMapObjDonkyRockGen : public GeographyObj { // Autogenerated +public: + TMapObjDonkyRockGen(const CrsData::SObject &); // 0x8029a6bc + virtual ~TMapObjDonkyRockGen(); // 0x8029a770 + virtual void reset(); // 0x8029a7fc + virtual void calc(); // 0x8029a870 + virtual void createColModel(J3DModelData *); // 0x8029a9b4 + bool appearRock(); // 0x8029a8c8 + void makeRockObject(int); // 0x8029a934 + // Inline + + s32 mSpawnInterval; // 0x14c + s32 mRockCount; // 0x150 + u32 mSpawnTimer; // 0x154 + TMapObjDonkyRock **mRocks; // 0x158 +}; + +#endif // MAPOBJDONKYROCKGEN_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index cf488224..4b3011c5 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -44,6 +44,7 @@ //#include "Shiraiwa/MapObjWanwan.h" #include "Shiraiwa/Objects/MapObjAward.h" #include "Shiraiwa/Objects/MapObjDonkyRock.h" +#include "Shiraiwa/Objects/MapObjDonkyRockGen.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Sato/GeographyObjMgr.h" @@ -192,7 +193,7 @@ GEO_OBJ_NEW(GeoKinojii); // GEO_OBJ_NEW(TMapObjUFO); GEO_OBJ_NEW_S(GeoWaterDown); GEO_OBJ_NEW_S(GeoWaterMiddleD); -// GEO_OBJ_NEW(TMapObjDonkyRockGen); +GEO_OBJ_NEW(TMapObjDonkyRockGen); // GEO_OBJ_NEW(TMapObjFireCircle); GEO_OBJ_NEW(GeoItemGen); // GEO_OBJ_NEW(TSMAButterflyGen); diff --git a/src/Shiraiwa/MapObjDonkyRockGen.cpp b/src/Shiraiwa/MapObjDonkyRockGen.cpp index e69de29b..1980cb07 100644 --- a/src/Shiraiwa/MapObjDonkyRockGen.cpp +++ b/src/Shiraiwa/MapObjDonkyRockGen.cpp @@ -0,0 +1,81 @@ +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" +#include "Sato/GeographyObjMgr.h" +#include "Shiraiwa/Objects/MapObjDonkyRock.h" +#include "Shiraiwa/Objects/MapObjDonkyRockGen.h" +#include "types.h" + +TMapObjDonkyRockGen::TMapObjDonkyRockGen(const CrsData::SObject &sObject) : GeographyObj(sObject) { + mSpawnInterval = 0; + mSpawnTimer = 0; + mRocks = nullptr; + + #line 26 + JUT_ASSERT_MSG(mObjData->mPathID != 0xffff, "TMapObjDonkyRockGen: Illegal Path ID"); + + int rockCount = sObject.mParam1; + if (rockCount < 1) { + rockCount = 1; + } + makeRockObject(rockCount); +} + +TMapObjDonkyRockGen::~TMapObjDonkyRockGen() { + delete []mRocks; +} + +void TMapObjDonkyRockGen::reset() { + resetObject(); + + clrObjFlagCheckGeoHitting(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + + mSpawnInterval = mObjData->mParam2; + + if (mSpawnInterval < 1) { + mSpawnInterval = 60; + } + + mSpawnTimer = 0; +} + +void TMapObjDonkyRockGen::calc() { + if (mSpawnTimer > mSpawnInterval) { + if (appearRock()) { + mSpawnTimer = 0; + } + } else { + mSpawnTimer++; + } +} + +bool TMapObjDonkyRockGen::appearRock() { + bool appeared = false; + + for (int i = 0; i < mRockCount; i++) { + TMapObjDonkyRock *rock = mRocks[i]; + + if (rock && rock->getState() == 0) { + rock->start(); + appeared = true; + break; + } + } + + return appeared; +} + +void TMapObjDonkyRockGen::makeRockObject(int count) { + mRockCount = count; + mRocks = new TMapObjDonkyRock *[mRockCount]; + for (int i = 0; i < mRockCount; i++) { + mRocks[i] = (TMapObjDonkyRock *)GetGeoObjMgr()->createSubObj(0x1197); + mRocks[i]->setObjData(mObjData); + } +} + +void TMapObjDonkyRockGen::createColModel(J3DModelData *) {} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 0663448377c60ba965c784b5ae13d17c631a9b9f Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 18:55:21 +1000 Subject: [PATCH 07/29] GeoObjMgr - Implement TMapObjDonkyTree. --- include/Shiraiwa/Objects/MapObjDonkyTree.h | 44 ++++++++++++ src/Sato/GeographyObjMgr.cpp | 7 +- src/Shiraiwa/MapObjDonkyTree.cpp | 82 ++++++++++++++++++++++ 3 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 include/Shiraiwa/Objects/MapObjDonkyTree.h diff --git a/include/Shiraiwa/Objects/MapObjDonkyTree.h b/include/Shiraiwa/Objects/MapObjDonkyTree.h new file mode 100644 index 00000000..89493762 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjDonkyTree.h @@ -0,0 +1,44 @@ +#ifndef MAPOBJDONKYTREE_H +#define MAPOBJDONKYTREE_H + +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" +#include "Sato/Objects/GeoTree.h" + +class TMapObjDonkyTree : public GeoMarioTree1 { // Autogenerated +public: + TMapObjDonkyTree(const CrsData::SObject &); // 0x802ad6d8 + virtual ~TMapObjDonkyTree(); // 0x802ad714 + virtual const char *getBmdFileName(); // 0x802ad7b4 + virtual GeoAnmTableEntry *getAnmTbl(); // 0x802ad7dc + virtual u16 getSizeAnmTbl() { return 8; } // 0x802ad80c + + static GeoAnmTableEntry sBckAnmTable; // 0x80415290 +}; // class TMapObjDonkyTree + + +class TMapObjDinoTree : public GeoMarioTree1 { +public: + TMapObjDinoTree(const CrsData::SObject &); + virtual ~TMapObjDinoTree(); + virtual void reset(); + virtual const char *getBmdFileName(); + virtual GeoAnmTableEntry *getAnmTbl(); + virtual u16 getSizeAnmTbl() { return 8; } + + static GeoAnmTableEntry sBckAnmTable; +}; // class TMapObjDinoTree + +class TMapObjDesertTree : public GeoMarioTree1 { +public: + TMapObjDesertTree(const CrsData::SObject &); + virtual ~TMapObjDesertTree(); + virtual void reset(); + virtual const char *getBmdFileName(); + virtual void createColModel(J3DModelData *); + virtual GeoAnmTableEntry *getAnmTbl() { return nullptr; } + virtual u16 getSizeAnmTbl() { return 0; } +}; // class TMapObjDesertTree + + +#endif // MAPOBJDONKYTREE_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 4b3011c5..1d50c537 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -45,6 +45,7 @@ #include "Shiraiwa/Objects/MapObjAward.h" #include "Shiraiwa/Objects/MapObjDonkyRock.h" #include "Shiraiwa/Objects/MapObjDonkyRockGen.h" +#include "Shiraiwa/Objects/MapObjDonkyTree.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Sato/GeographyObjMgr.h" @@ -104,7 +105,7 @@ GEO_OBJ_NEW(GeoCannon); // GEO_OBJ_NEW_S(TMapObjWanwanPile); // GEO_OBJ_NEW(TMapObjSkyShip); GEO_OBJ_NEW_S(TMapObjDonkyRock); -// GEO_OBJ_NEW_S(TMapObjDonkyTree); +GEO_OBJ_NEW(TMapObjDonkyTree); GEO_OBJ_NEW(GeoDkCloud); GEO_OBJ_NEW_S(GeoWaterUp); GEO_OBJ_NEW_S(GeoWaterUp2); @@ -174,7 +175,7 @@ GEO_OBJ_NEW(TMapObjAwardItemBox); GEO_OBJ_NEW(TMapObjAntLion); // GEO_OBJ_NEW(TMapObjPakkun); GEO_OBJ_NEW(GeoKinojii); -// GEO_OBJ_NEW(TMapObjDinoTree); +GEO_OBJ_NEW(TMapObjDinoTree); // GEO_OBJ_NEW(TMapObjDemoFountain); // GEO_OBJ_NEW(TMapObjKpGear); // GEO_OBJ_NEW(TMapObjKpFireBar); @@ -182,7 +183,7 @@ GEO_OBJ_NEW(GeoKinojii); // GEO_OBJ_NEW(TMapObjPtera); // GEO_OBJ_NEW(TMapObjPeachTree2); // GEO_OBJ_NEW(TMapObjYoshiHeli); -// GEO_OBJ_NEW(TMapObjDesertTree); +GEO_OBJ_NEW(TMapObjDesertTree); // GEO_OBJ_NEW(TMapObjWluSearchLight); // GEO_OBJ_NEW(TMapObjVentilator); // GEO_OBJ_NEW_S(TShineArrow); diff --git a/src/Shiraiwa/MapObjDonkyTree.cpp b/src/Shiraiwa/MapObjDonkyTree.cpp index e69de29b..48e6fa69 100644 --- a/src/Shiraiwa/MapObjDonkyTree.cpp +++ b/src/Shiraiwa/MapObjDonkyTree.cpp @@ -0,0 +1,82 @@ +#include "Shiraiwa/Objects/MapObjDonkyTree.h" +#include "JSystem/J3D/J3DFrameCtrl.h" +#include "Sato/GeographyObj.h" +#include "Sato/Objects/GeoTree.h" +#include "types.h" + +GeoAnmTableEntry TMapObjDonkyTree::sBckAnmTable = { + 0, "DonkyTree1_wait.bck" +}; + +TMapObjDonkyTree::TMapObjDonkyTree(const CrsData::SObject &sObject) : GeoMarioTree1(sObject) {} + +TMapObjDonkyTree::~TMapObjDonkyTree() {} + +const char *TMapObjDonkyTree::getBmdFileName() { + static const char *cTreeBmdName = "DonkyTree1.bmd"; + return cTreeBmdName; +} + +GeoAnmTableEntry *TMapObjDonkyTree::getAnmTbl() { + if (availBckAnm()) { + return &sBckAnmTable; + } + return nullptr; +} + +GeoAnmTableEntry TMapObjDinoTree::sBckAnmTable = { + 0, "DinoTree1_wait.bck" +}; + +TMapObjDinoTree::TMapObjDinoTree(const CrsData::SObject &sObject) : GeoMarioTree1(sObject) {} + +TMapObjDinoTree::~TMapObjDinoTree() {} + +void TMapObjDinoTree::reset() { + GeographyObj::resetObject(); + _58 = 0; + clrAllCheckKartHitFlag(); + clrObjFlagCheckItemHitting(); + AnmController *anmCtrl = getAnmCtrl(); + if (anmCtrl) { + J3DFrameCtrl *ctrl = getAnmCtrl()->getFrameCtrl(0); + ctrl->setAttribute(2); + ctrl->setRate(((getGeoRnd()->get_ufloat_1() * 2 - 1) * 0.3f + 1.0f)); + } +} + +const char *TMapObjDinoTree::getBmdFileName() { + static const char *cTreeBmdName = "DinoTree1.bmd"; + return cTreeBmdName; +} + +GeoAnmTableEntry *TMapObjDinoTree::getAnmTbl() { + if (availBckAnm()) { + return &sBckAnmTable; + } + return nullptr; +} + +TMapObjDesertTree::TMapObjDesertTree(const CrsData::SObject &sObject) : GeoMarioTree1(sObject) { + clrObjFlagLODBias(); +} + +TMapObjDesertTree::~TMapObjDesertTree() {} + +void TMapObjDesertTree::reset() { + GeographyObj::resetObject(); + _58 = 1; + setAllCheckKartHitFlag(); + setObjFlagCheckItemHitting(); +} + +const char *TMapObjDesertTree::getBmdFileName() { + static const char *cTreeBmdName = "DesertTree1.bmd"; + return cTreeBmdName; +} + +void TMapObjDesertTree::createColModel(J3DModelData *modelData) { + createBoundsCylinder(modelData, 210.0f, 700.0f); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From ad23fef21673fe3b19bff157dafd6392061de6cd Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 19:02:54 +1000 Subject: [PATCH 08/29] Fix Coord3D function return types based on additional context from MapObjDossun. --- include/Shiraiwa/Coord3D.h | 31 ++++++++++++++++++------------- src/Shiraiwa/Coord3D.cpp | 8 ++++---- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/include/Shiraiwa/Coord3D.h b/include/Shiraiwa/Coord3D.h index 0205eead..aa1f51f3 100644 --- a/include/Shiraiwa/Coord3D.h +++ b/include/Shiraiwa/Coord3D.h @@ -35,6 +35,10 @@ class TFreeMove { _18 = false; } + void setUnknown24(f32 value) { + _24 = value; + } + private: JGeometry::TVec3f mTagret; JGeometry::TVec3f *mpPos; @@ -49,13 +53,13 @@ class TPathMove { public: TPathMove(const CrsData::SObject *); virtual ~TPathMove() {} - void update(); + u8 update(); void init(JGeometry::TVec3f *, JGeometry::TVec3f *); void reset(); void setTargetNode(); void setTargetNode(u16, f32, f32); void getNodePosition(JGeometry::TVec3f *, u16); - void getNextNode(); + u16 getNextNode(); void updatePos(); void checkReachTarget(); @@ -64,15 +68,16 @@ class TPathMove { void setTargetNode(u16); void getNodeDir(u16, JGeometry::TVec3f *); -protected: - const CrsData::SObject *mpObj; // 04 - s16 _8; // - JGeometry::TVec3f *mpPos; // 0c - JGeometry::TVec3f *mpVel; // 10 - f32 _14; - f32 _18; - bool _1c; - PLACEHOLDER_BYTES(0x1d, 0x24); +public: + const CrsData::SObject *mpObj; // 0x4 + s16 _8; // 0x8 + JGeometry::TVec3f *mpPos; // 0xc + JGeometry::TVec3f *mpVel; // 0x10 + f32 _14; // 0x14 + f32 _18; // 0x18 + bool _1c; // 0x1c, 3 bytes padding + f32 _20; // 0x20 + //PLACEHOLDER_BYTES(0x1d, 0x24); }; // Size: 0x24 class TFreeRotate { @@ -81,7 +86,7 @@ class TFreeRotate { virtual ~TFreeRotate() {} void init(JGeometry::TPos3f *); void setTargetVec(const JGeometry::TVec3f &, const JGeometry::TVec3f &, f32, f32, f32); - void setTargetVec(const JGeometry::TVec3f &, f32, f32, f32, u8); + void setTargetVec(const JGeometry::TVec3f &, f32, f32, f32, unsigned char); void setTargetQuat(const JGeometry::TQuat4f &, f32, f32, f32); bool update(); void angleUpdate(); @@ -109,5 +114,5 @@ class TFreeRotate { f32 mTarget; bool _3c; }; - + #endif // COORD3D_H diff --git a/src/Shiraiwa/Coord3D.cpp b/src/Shiraiwa/Coord3D.cpp index fb048313..10d08305 100644 --- a/src/Shiraiwa/Coord3D.cpp +++ b/src/Shiraiwa/Coord3D.cpp @@ -23,7 +23,7 @@ void TFreeMove::velUpdate(JGeometry::TVec3f &, f32, f32) {} TPathMove::TPathMove(const CrsData::SObject *) {} -void TPathMove::update() {} +u8 TPathMove::update() {} // return type is some bool/integer type. void TPathMove::init(JGeometry::TVec3f *, JGeometry::TVec3f *) {} @@ -35,7 +35,7 @@ void TPathMove::setTargetNode(u16, f32, f32) {} void TPathMove::getNodePosition(JGeometry::TVec3f *, u16) {} -void TPathMove::getNextNode() {} +u16 TPathMove::getNextNode() {} void TPathMove::updatePos() {} @@ -57,7 +57,7 @@ void TFreeRotate::init(JGeometry::TPos3f *matrix) { void TFreeRotate::setTargetVec(const JGeometry::TVec3f &, const JGeometry::TVec3f &, f32, f32, f32) {} -void TFreeRotate::setTargetVec(const JGeometry::TVec3f &, f32, f32, f32, u8) {} +void TFreeRotate::setTargetVec(const JGeometry::TVec3f &, f32, f32, f32, unsigned char) {} void TFreeRotate::setTargetQuat(const JGeometry::TQuat4f &q, f32 inc, f32 maxSpd, f32 target) { mpMatrix->getQuat(_18); @@ -95,7 +95,7 @@ void TFreeRotate::angleUpdate() { void TFreeRotate::velUpdate() { if (mSpeed < mMaxSpeed) { - mSpeed += mSpeedInc; + mSpeed += mSpeedInc; if (mSpeed > mMaxSpeed) { mSpeed = mMaxSpeed; } From b7e68227dff7febe1c73ab3a3e396bb7b249ff6f Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 19:05:27 +1000 Subject: [PATCH 09/29] GeoObjMgr - Implement majority of TMapObjDossun. Note one isssue around `mAnmCtrl->ChangeTransAnm(0);` - where it looks like this function may cause some register mismatches. --- include/Shiraiwa/Objects/MapObjDossun.h | 70 +++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/MapObjDossun.cpp | 362 ++++++++++++++++++++++++ 3 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjDossun.h diff --git a/include/Shiraiwa/Objects/MapObjDossun.h b/include/Shiraiwa/Objects/MapObjDossun.h new file mode 100644 index 00000000..1e8d2e8d --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjDossun.h @@ -0,0 +1,70 @@ +#ifndef MAPOBJDOSSUN_H +#define MAPOBJDOSSUN_H + +#include "JSystem/J3D/J3DAnmTexPattern.h" +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/J3DAnmObject.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Coord3D.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjDossun : public TMapObjStamper, StateObserver { +public: + TMapObjDossun(const CrsData::SObject &); + virtual ~TMapObjDossun(); + virtual void loadAnimation(); + virtual void createModel(JKRSolidHeap *, u32); + virtual void reset(); + virtual void calc(); + virtual void update(); + virtual const char *getBmdFileName(); + virtual const char *getShadowBmdFileName(); + virtual void createColModel(J3DModelData *); + virtual void doKartColCallBack(int param_1); + virtual u32 getReleaseFrame() { return 100; }; + virtual void MoveExec(); + virtual void InitExec(); + + void initFunc_Start(); + void doFunc_Start(); + void initFunc_Up(); + void doFunc_Up(); + void initFunc_Top(); + void doFunc_Top(); + void initFunc_Down(); + void doFunc_Down(); + void makeGroundEmitter(); + void initFunc_Bottom(); + void doFunc_Bottom(); + void initFunc_Die(); + void doFunc_Die(); + void shakeCamera(); + void checkItemHitting(); + + static JGeometry::TVec3f sDieVelocity0; + static const JGeometry::TVec3f scDownVelocity0; + static StateFuncSet sTable[6]; + static J3DAnmTransform *sDossunBckAnmTrans; + static J3DMtxCalc *sDossunBckMtxCalc; + static J3DAnmTexPattern *sDossunBtpAnm; + static f32 sBtpPlyFrameRate; + static f32 sBtpRevFrameRate; + static f32 sDieGravityY; + + +private: + J3DAnmObjMaterial _180; // 0x180 + s16 mHeight; // 0x1a0 + u16 _1a2; // 0x1a2 + u8 _1a4; // 0x1a4 + u8 _1a5; // 0x1a5 - Padding...? + u16 _1a6; // 0x1a6 + TFreeMove mFreeMove; // 0x1a8 + TPathMove *mPathMove; // 0x1d0 + s16 _1d4; // 0x1d4 +}; // 0x1d8 + +#endif // MAPOBJDOSSUN_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 1d50c537..ed2569ce 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -46,6 +46,7 @@ #include "Shiraiwa/Objects/MapObjDonkyRock.h" #include "Shiraiwa/Objects/MapObjDonkyRockGen.h" #include "Shiraiwa/Objects/MapObjDonkyTree.h" +#include "Shiraiwa/Objects/MapObjDossun.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Sato/GeographyObjMgr.h" @@ -73,7 +74,7 @@ GEO_OBJ_NEW_S(GeoStartLine); GEO_OBJ_NEW(GeoMarioTree1); GEO_OBJ_NEW(GeoMarioKinoko1); GEO_OBJ_NEW(GeoMarioFlower1); -// GEO_OBJ_NEW(TMapObjDossun); +GEO_OBJ_NEW(TMapObjDossun); GEO_OBJ_NEW(GeoNormCar); GEO_OBJ_NEW_S(GeoCarShadow); GEO_OBJ_NEW_S(GeoBombShadow); diff --git a/src/Shiraiwa/MapObjDossun.cpp b/src/Shiraiwa/MapObjDossun.cpp index e69de29b..04febfae 100644 --- a/src/Shiraiwa/MapObjDossun.cpp +++ b/src/Shiraiwa/MapObjDossun.cpp @@ -0,0 +1,362 @@ +//#include "JSystem/JAudio/JASFakeMatch4.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/RaceMgr.h" +#include "Sato/AnmController.h" +#include "Sato/JPEffectMgr.h" +#include "Sato/ObjUtility.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Coord3D.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "Yamamoto/kartCtrl.h" +#include "types.h" +#include "Shiraiwa/Objects/MapObjDossun.h" + + +StateObserver::StateFuncSet TMapObjDossun::sTable[6] = { + { 0, &TMapObjDossun::initFunc_Bottom, &TMapObjDossun::doFunc_Bottom }, + { 1, &TMapObjDossun::initFunc_Up, &TMapObjDossun::doFunc_Up }, + { 2, &TMapObjDossun::initFunc_Die, &TMapObjDossun::doFunc_Die }, + { 3, &TMapObjDossun::initFunc_Start, &TMapObjDossun::doFunc_Start }, + { 4, &TMapObjDossun::initFunc_Top, &TMapObjDossun::doFunc_Top }, + { 5, &TMapObjDossun::initFunc_Down, &TMapObjDossun::doFunc_Down }, +}; + +const JGeometry::TVec3f TMapObjDossun::scDownVelocity0(0.0f, 100.0f, 0.0f); +JGeometry::TVec3f TMapObjDossun::sDieVelocity0(0.0f, 200.0f, 0.0f); + +J3DAnmTransform *TMapObjDossun::sDossunBckAnmTrans; +J3DMtxCalc *TMapObjDossun::sDossunBckMtxCalc; +J3DAnmTexPattern *TMapObjDossun::sDossunBtpAnm; + +f32 TMapObjDossun::sBtpRevFrameRate = -0.6f; +f32 TMapObjDossun::sBtpPlyFrameRate = 0.6f; +f32 TMapObjDossun::sDieGravityY = 5.0f; + + +TMapObjDossun::TMapObjDossun(const CrsData::SObject &sObject) : TMapObjStamper(sObject), StateObserver(), mHeight(0x3e8), _1a2(0xfa), _1a4(0x1e) { + NewAnmCtrl(); + createSoundMgr(); + mPathMove = new TPathMove(&sObject); +} + +TMapObjDossun::~TMapObjDossun() { + delete mPathMove; +} + +void TMapObjDossun::reset() { + GeographyObj::resetObject(); + setObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + _58 = 10; + + if (mObjData->mParam1 != 0) { + _1a2 = mObjData->mParam1; + } + + if (mObjData->mParam2 != 0) { + _1a4 = mObjData->mParam2; + } + + if (IsPathMove()) { + mPathMove->getNodePosition(&mPos, 0); + TPathMove *pathMove = mPathMove; + pathMove->_14 = 10.0f; + pathMove->_18 = 10.0f; + pathMove->_20 = 25.0f; + } + + _1d4 = mObjData->mParam3; + if (_1d4 < 0) { + _1d4 = 0; + } + + setState(1); + + CrsGround crsGround(RCMGetCourse()); + crsGround.search(mPos); + mHeight = mPos.y - crsGround.getHeight(); + + #line 108 + JUT_ASSERT(mHeight >= 0); + + mFreeMove.init(&mPos, &mVel, 200.0f); + mPathMove->init(&mPos, &mVel); + f32 local_28 = mHeight; + if (local_28 == 0.0f) { + local_28 = _1a4; + TPathMove *pathMove = mPathMove; + pathMove->_14 = 1.4f; + pathMove->_18 = local_28; + pathMove->_20 = (local_28 * 0.5f) * (local_28 * 0.5f); + } + + ResetState(); + mAnmCtrl->Reset(); + mAnmCtrl->ChangeTransAnm(0); // FIX: Is this function causing register mismatches? + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->setFlag(); + } + + _180.resetFrame(); + _180.getFrameCtrl()->setAttribute(0); + resetFrame(); +} + +void TMapObjDossun::loadAnimation() { + J3DModelData *modelData = *mModel.mModelData; + void *ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/Dossun1.bck"); + J3DAnmObjTrans::setupTransAnmData(&sDossunBckAnmTrans, &sDossunBckMtxCalc, modelData, ptrCourseArc); + ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/Dossun1.btp"); + J3DAnmObjMaterial::setupTexPatternAnmData(&sDossunBtpAnm, modelData, ptrCourseArc); +} + +const char *TMapObjDossun::getShadowBmdFileName() { + static const char *cShadowBmdName = "/Objects/Dossun1_kage.bmd"; + return cShadowBmdName; +} + +void TMapObjDossun::createColModel(J3DModelData* modelData) { + f32 scaleXZ = mScale.x > mScale.z + ? mScale.x + : mScale.z; + + f32 ratio = mScale.y / scaleXZ; + static const f32 cBoundHeight = ratio * 800.0f; + + createBoundsCylinder(modelData, 500.0f, cBoundHeight); +} + +void TMapObjDossun::createModel(JKRSolidHeap *heap, u32 p2) { + mModel.createDifferedModel(heap, p2, 0x40000, 0); + + AnmController *anmCtrl = mAnmCtrl; + AnmControlTrans *anmTrans = new AnmControlTrans(); + anmCtrl->mTrans = anmTrans; + anmTrans = anmCtrl->mTrans; + + anmTrans->initAnm(1, &mModel); + mAnmCtrl->mTrans->registration(0, sDossunBckAnmTrans, sDossunBckMtxCalc); + mAnmCtrl->mTrans->getFrameCtrl(0)->setAttribute(2); + + _180.setExModel(&mModel); + _180.mAnmBase = sDossunBtpAnm; + _180.initFrameCtrl(_180.getAnmBase()); + +} + +const char *TMapObjDossun::getBmdFileName() { + static const char *cBmdName = "/Objects/Dossun1.bmd"; + return cBmdName; +} + +void TMapObjDossun::update() { + _180.anmFrameProc(); + setModelMatrixAndScale(); + mModel.update(0); +} + +void TMapObjDossun::doKartColCallBack(int kartIdx) { + if ((GetKartCtrl()->getKartBody(kartIdx)->mCarStatus & 0x40000)) { + setState(5); + } else { + startStamp(kartIdx); + } +} + +void TMapObjDossun::initFunc_Start() {} + +void TMapObjDossun::doFunc_Start() { + if (getStateCount() > _1d4) { + setState(1); + } +} + +void TMapObjDossun::initFunc_Up() { + JGeometry::TVec3f targetOffset; + + _180.setFrame(_180.getFrameCtrl()->getEnd()); + _180.setRate(sBtpRevFrameRate); + targetOffset.set(0.0f, (f32)mHeight, 0.0f); + mFreeMove.setTargetOffsetUniform(targetOffset, 120); +} + +void TMapObjDossun::doFunc_Up() { + if (!mFreeMove.hasTarget()) { + setState(1); + } +} + +void TMapObjDossun::initFunc_Top() { + _1a6 = 0; + + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->setFlag(); + } + + if (IsPathMove()) { + mPathMove->setTargetNode(); + mVel.zero(); + } +} + +void TMapObjDossun::doFunc_Top() { + s16 frameEnd; + AnmControlTrans *pAVar2; + u32 uVar3; + J3DAnmObjTrans *pJVar4; + + if (mPathMove->_1c != false) { + moveShadowModel(); + return; + } + + if (mHeight == 0) { + if (_1a6 < _1a2) { + if (_1a6 == 0) { + shakeCamera(); + } + _1a6++; + return; + } + + _1a6 = 0; + + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->setFlag(); + } + + if (IsPathMove()) { + mPathMove->setTargetNode(); + mVel.zero(); + } + return; + } + + frameEnd = mAnmCtrl->mTrans->getObj(0)->getFrameCtrl()->getEnd(); + if (_1a6 < (u32)(_1a2 + frameEnd * 3)) { + if (_1a6 == _1a2) { + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->resetFlag(); + } + } + _1a6++; + + } else { + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->setFlag(); + } + setState(2); + } + + if ((u32)(_1a2 + frameEnd * 3 - 6) == _1a6) { + _180.setRate(sBtpPlyFrameRate); + } +} + +void TMapObjDossun::initFunc_Down() { + JGeometry::TVec3f local_18; + mVel.set(scDownVelocity0); + local_18.set(0.0f, (f32)-mHeight, 0.0f); + mFreeMove.setUnknown24(30.0f); + mFreeMove.setTargetOffset(local_18, 10.0f, 200.0f); +} + +void TMapObjDossun::doFunc_Down() { + if (!mFreeMove.hasTarget()) { + shakeCamera(); + makeGroundEmitter(); + getSoundMgr()->setSe(0x40033); + setState(3); + } +} + +void TMapObjDossun::makeGroundEmitter() { + JPEffectMgr::getEffectMgr()->createEmt("mk_dossun_a", mPos); + JPEffectMgr::getEffectMgr()->createEmt("mk_dossun_b", mPos); + JPEffectMgr::getEffectMgr()->createEmt("mk_dossun_c", mPos); +} + +void TMapObjDossun::initFunc_Bottom() { + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->resetFlag(); + } + _1a6 = 0; +} + +void TMapObjDossun::doFunc_Bottom() { + s16 sVar1; + u32 uVar2; + J3DAnmObjTrans *pJVar3; + AnmControlTrans *pAVar4; + + if (_1a6 < _1a4) { + if (_1a6 == (u32)mAnmCtrl->mTrans->getObj(0)->getFrameCtrl()->getEnd()) { + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->setFlag(); + } + } + _1a6++; + + } else { + setState(4); + } +} + +void TMapObjDossun::initFunc_Die() { + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + mFreeMove.releaseTarget(); + mVel.set(sDieVelocity0); + _180.setFrame(_180.getFrameCtrl()->getEnd()); +} + +void TMapObjDossun::doFunc_Die() { + mVel.y -= sDieGravityY; + mPos.add(mVel); + if (mPos.y > mObjData->position.y) { + mPos.y = mObjData->position.y; + mVel.zero(); + setObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + setState(1); + } +} + +void TMapObjDossun::shakeCamera() { + ObjUtility::executeShakeCamera(mPos, 10000.0f, 0.4f, 2000.0); +} + +void TMapObjDossun::calc() { + ExecuteState(); + mFreeMove.update(); + + if (IsPathMove() && getState() == 1) { + mPathMove->update(); + } + + checkItemHitting(); + _180.update(); + + for (int kartIdx = 0; kartIdx < RCMGetManager()->getKartNumber(); kartIdx++) { + if ((GetKartCtrl()->GetKartStatus(kartIdx) & 0x200000000) == 0) { + endStamp(kartIdx); + } + } + frameProc(); +} + +void TMapObjDossun::checkItemHitting() { + if (tstItemHitting()) { + if (mColItemObj->mItemKind == 7 || mColItemObj->mItemKind == 8) { + mFreeMove.releaseTarget(); + setState(5); + } + } +} + +void TMapObjDossun::InitExec() { Observer_FindAndInit(TMapObjDossun, 6); } + +void TMapObjDossun::MoveExec() { Observer_FindAndExec(TMapObjDossun, 6); } + +#include "JSystem/JAudio/JASFakeMatch2.h" From 64afde7b0b88d79f4b3e64cecd11395123a4f6d5 Mon Sep 17 00:00:00 2001 From: MJ Date: Wed, 22 Jul 2026 22:30:14 +1000 Subject: [PATCH 10/29] GeoObjMgr - Add TMapObjWanwan, TMapObjWanwanChain and TMapObjWanwanPile. These were previously decompiled by Sware, so only the import and object creation is present in this commit. --- src/Sato/GeographyObjMgr.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index ed2569ce..272d6be8 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -39,15 +39,14 @@ #include "Shiraiwa/JugemMain.h" #include "Shiraiwa/JugemRodItem.h" #include "Shiraiwa/LensFlare.h" -//#include "Shiraiwa/MapObjDossun.h" //#include "Shiraiwa/MapObjPoihana.h" -//#include "Shiraiwa/MapObjWanwan.h" #include "Shiraiwa/Objects/MapObjAward.h" #include "Shiraiwa/Objects/MapObjDonkyRock.h" #include "Shiraiwa/Objects/MapObjDonkyRockGen.h" #include "Shiraiwa/Objects/MapObjDonkyTree.h" #include "Shiraiwa/Objects/MapObjDossun.h" #include "Shiraiwa/Objects/MapObjPool.h" +#include "Shiraiwa/Objects/MapObjWanwan.h" #include "Sato/GeographyObjMgr.h" #define GEO_OBJ_NEW(GeoClassName) \ @@ -101,9 +100,9 @@ GEO_OBJ_NEW_S(TJugemFlag); GEO_OBJ_NEW_S(TJugemHeadLamp); GEO_OBJ_NEW(GeoSignal); GEO_OBJ_NEW(GeoCannon); -// GEO_OBJ_NEW(TMapObjWanwan); -// GEO_OBJ_NEW_S(TMapObjWanwanChain); -// GEO_OBJ_NEW_S(TMapObjWanwanPile); +GEO_OBJ_NEW(TMapObjWanwan); +GEO_OBJ_NEW_S(TMapObjWanwanChain); +GEO_OBJ_NEW_S(TMapObjWanwanPile); // GEO_OBJ_NEW(TMapObjSkyShip); GEO_OBJ_NEW_S(TMapObjDonkyRock); GEO_OBJ_NEW(TMapObjDonkyTree); From d8965228fc429c4bbae2a6e23af225e8c47af773 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 00:05:06 +1000 Subject: [PATCH 11/29] Add class accessors to Course.h for `mDirX`, `mDirY` and `mDirZ`. Note that these are inlines used by Coord3DUtil, so it shouldn't impact overall match. --- include/Kaneshige/Course/Course.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/Kaneshige/Course/Course.h b/include/Kaneshige/Course/Course.h index 5e64b2ee..104ab482 100644 --- a/include/Kaneshige/Course/Course.h +++ b/include/Kaneshige/Course/Course.h @@ -229,6 +229,10 @@ class Course f32 getGroundThickness() const { return sGndThickness; } + JGeometry::TVec3f *getDirZ() { return &mDirZ; }; + JGeometry::TVec3f *getDirY() { return &mDirY; }; + JGeometry::TVec3f *getDirX() { return &mDirX; }; + private: // add all documented stuff from Ghidra static u16 sDrawAreaModel; static bool sForceDebugFogSetting; From 6dcff51268fdcb64a4ebb9f6d9e0ddfa1b6fb24e Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 00:24:28 +1000 Subject: [PATCH 12/29] Implement Coord3DUtil. This is a complete match for the class, excluding the last part of `TFreeFallShakeSky::reflect()` where there is a register mismatch. --- include/Shiraiwa/Coord3DUtil.h | 173 ++++++++ src/Shiraiwa/Coord3DUtil.cpp | 736 +++++++++++++++++++++++++++++++++ 2 files changed, 909 insertions(+) create mode 100644 include/Shiraiwa/Coord3DUtil.h diff --git a/include/Shiraiwa/Coord3DUtil.h b/include/Shiraiwa/Coord3DUtil.h new file mode 100644 index 00000000..0bd83c8f --- /dev/null +++ b/include/Shiraiwa/Coord3DUtil.h @@ -0,0 +1,173 @@ +#ifndef COORD3DUTIL_H +#define COORD3DUTIL_H + +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JGeometry/Vec.h" +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/Course/CrsGround.h" +#include "Sato/stMath.h" +#include "Shiraiwa/Coord3D.h" + +class TPathUtil { +public: + TPathUtil(); + TPathUtil(const CrsData::SObject *); + virtual ~TPathUtil(); + + virtual void reset(); + void getDirection(JGeometry::TVec3f& out); + float getDistance(); + u16 getNextNode(); + + u16 getPointIndex() const { return mPointIndex; } + void setPointIndex(u16 pointIndex) { mPointIndex = pointIndex; } + +public: + const CrsData::SObject *mObj; // 0x4 + u16 mPointIndex; // 0x8 + s8 mDirection; // 0xA + f32 mDistance; // 0xC + bool mDistanceDirty; // 0x10 - 3 bytes padding. + +}; // 0x14 - confirmed via TMapObjUFO Constructor. + +class TPathUtilInterrupt : public TPathUtil { +public: + TPathUtilInterrupt(const CrsData::SObject *sObject) : TPathUtil(sObject) { + _14.set(0.0f, 0.0f ,0.0f); + _20 = 0; + } + virtual void reset(); + void getCurrentNodePos(JGeometry::TVec3f *); + void getNextNodePos(JGeometry::TVec3f *); + void updateNode(); + + JGeometry::TVec3f _14; + bool _20; +}; + +class TPathWalk { +public: + TPathWalk(const CrsData::SObject *); + virtual ~TPathWalk(); + bool init(JGeometry::TVec3f *, JGeometry::TVec3f *, JGeometry::TPos3f *); + bool reset(); + void setParameters(f32, f32, f32, f32, f32); + void setCheckLength(f32); + s16 update(); + void dirUpdate(); + void posUpdate(); + bool checkReachTarget(); + void forceTurn(const JGeometry::TVec3f &); + void forceTurn(const JGeometry::TVec3f &, const JGeometry::TVec3f &); + + static s16 sNearlyReachTargetLength; + + TFreeRotate *_4; // 0x4 + TFreeRotate *_8; // 0x8 + CrsGround *crsGround; // 0xc + JGeometry::TVec3f *_10; // 0x10 + JGeometry::TVec3f *_14; // 0x14 + JGeometry::TPos3f *_18; // 0x18 + JGeometry::TPos3f _1c; // 0x1c + JGeometry::TPos3f _4c; // 0x4c + f32 _7c; // 0x7c - TVec3f? + f32 _80; // 0x80 + f32 _84; // 0x84 + TPathUtilInterrupt *_88; // 0x88 + f32 mCheckLength; // 0x8c + f32 _90; // 0x90 + u8 _94; // 0x94 + f32 _98; // 0x98 + f32 _9c; // 0x9c + f32 _a0; // 0xa0 + f32 _a4; // 0xa4 +}; + + +class TFreeFly { +public: + TFreeFly(); + virtual ~TFreeFly(); + virtual void reset(); + void init(JGeometry::TVec3f *, JGeometry::TVec3f *, JGeometry::TPos3f *); + void setParameters(f32, f32, f32); + u8 update(); + void dirUpdate(); + void posUpdate(); + bool checkReachTarget(); + + void forceTurn(JGeometry::TVec3f &); + + static s16 sNearlyReachTargetLength; + + TFreeRotate *mFreeRotate; // 0x4 + JGeometry::TVec3f *mPosition; // 0x8 + JGeometry::TVec3f *mVelocity; // 0xc + JGeometry::TPos3f *_10; // 0x10 + JGeometry::TPos3f _14; // 0x14 + JGeometry::TVec3f _44; // 0x44 + f32 mSpeed; // 0x50 + u8 _54; // 0x54 + f32 _58; // 0x58 + f32 _5c; // 0x5c +}; + +class TFreeFall { +public: + TFreeFall(); + TFreeFall(JGeometry::TVec3f *pos, JGeometry::TVec3f *vel, JGeometry::TPos3f *rot); + virtual ~TFreeFall(); + virtual bool update(); // 0xc + virtual void reset(); // 0x10 + virtual void roll(); // 0x14 + virtual void reflect(const JGeometry::TVec3f &); + virtual void rotate(); + virtual void getGravity(JGeometry::TVec3f *); + virtual void getReflect(const JGeometry::TVec3f &, JGeometry::TVec3f *); + virtual void addAccel(const JGeometry::TVec3f &); + void init(JGeometry::TVec3f *, JGeometry::TVec3f *, JGeometry::TPos3f *); + + f32 _4; + f32 _8; + f32 _c; + f32 _10; + f32 mRotSpeed; + f32 mGravity; + bool mEnabled; + JGeometry::TVec3f *mPos; // 0x20 + JGeometry::TVec3f *mVel; // 0x24 + JGeometry::TPos3f *mRot; // 0x28 +}; + +class TFreeFallShakeSky : public TFreeFall { +public: + TFreeFallShakeSky(JGeometry::TVec3f *pos, JGeometry::TVec3f *vel, JGeometry::TPos3f *rot) : TFreeFall(pos, vel, rot) { + mRnd = nullptr; + } + virtual ~TFreeFallShakeSky(); + virtual void reset(); + virtual void reflect(const JGeometry::TVec3f &); + virtual void rotate(); + virtual void getGravity(JGeometry::TVec3f *); + virtual void getReflect(const JGeometry::TVec3f &, JGeometry::TVec3f *); + + // static scPowMax; + // static scSmallJumpMin; + // static scSmallJumpMax; + + stRandom *mRnd; + f32 _30; + f32 _34; + u8 _38; +}; + +class TFreeFallDonkyRock { +public: + ~TFreeFallDonkyRock(); + void reflect(const JGeometry::TVec3f &); + void reset(); + void getReflect(const JGeometry::TVec3f &, JGeometry::TVec3f *); +}; + +#endif // COORD3DUTIL_H diff --git a/src/Shiraiwa/Coord3DUtil.cpp b/src/Shiraiwa/Coord3DUtil.cpp index e69de29b..b55a6aa7 100644 --- a/src/Shiraiwa/Coord3DUtil.cpp +++ b/src/Shiraiwa/Coord3DUtil.cpp @@ -0,0 +1,736 @@ +#include "Shiraiwa/Coord3DUtil.h" +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/Course/CrsGround.h" +#include "Kaneshige/RaceMgr.h" +#include "Shiraiwa/Coord3D.h" +#include "Shiraiwa/SiUtil.h" +#include "dolphin/mtx.h" +#include "math.h" +#include "types.h" + +s16 TPathWalk::sNearlyReachTargetLength = 300; +s16 TFreeFly::sNearlyReachTargetLength = 500; + +TPathUtil::TPathUtil() {} + +TPathUtil::TPathUtil(const CrsData::SObject *sObject) { + setPointIndex(0); + mDirection = 1; + mObj = sObject; +} + +TPathUtil::~TPathUtil() {} + +void TPathUtil::reset() { + mDistanceDirty = true; + mDistance = 0.0f; + setPointIndex(0); + mDirection = 1; +} + +u16 TPathUtil::getNextNode() { + s16 nextNode = getPointIndex(); + nextNode += mDirection; + + CrsData::PathData *pathData = RCMGetCourse()->getCrsData()->getPathData(mObj->mPathID); + if (nextNode >= pathData->getPointNumber()) { + pathData = RCMGetCourse()->getCrsData()->getPathData(mObj->mPathID); + if (pathData->isClosed()) { + nextNode = 0; + } else { + nextNode = getPointIndex() - 1; + mDirection = -1; + } + } else { + if (nextNode < 0) { + nextNode = getPointIndex() + 1; + mDirection = 1; + } + } + return nextNode; +} + +void TPathUtil::getDirection(JGeometry::TVec3f &out) { + int pointIndex = getPointIndex(); + + CrsData::PointData* cur = + RCMGetCourse()->getCrsData()->getPointData(mObj->mPathID, pointIndex); + JGeometry::TVec3f current; + current.set(cur->pos); + + s16 pointIdx = getPointIndex(); + pointIdx += mDirection; + + CrsData::PathData *path = + RCMGetCourse()->getCrsData()->getPathData(mObj->mPathID); + + if (pointIdx >= path->getPointNumber()) { + if (RCMGetCourse()->getCrsData()->getPathData(mObj->mPathID)->isClosed()) { + pointIdx = 0; + } else { + pointIdx = getPointIndex() - 1; + mDirection = -1; + } + + } else if (pointIdx < 0) { + pointIdx = getPointIndex() + 1; + mDirection = 1; + } + + CrsData::PointData *next = RCMGetCourse()->getCrsData()->getPointData(mObj->mPathID, pointIdx); + + JGeometry::TVec3f nextPos; + nextPos.set(next->pos); + + JGeometry::TVec3f dir; + dir.sub(nextPos, current); + dir.normalize(); + out.set(dir); +} + +f32 TPathUtil::getDistance() { + if (mDistanceDirty) { + int pointIndex = getPointIndex(); + + CrsData::PointData* cur = RCMGetCourse()->getCrsData()->getPointData(mObj->mPathID, pointIndex); + + JGeometry::TVec3f current; + current.set(cur->pos); + + s16 pointIdx = getPointIndex(); + pointIdx += mDirection; + + CrsData::PathData* path = RCMGetCourse()->getCrsData()->getPathData(mObj->mPathID); + + if (pointIdx >= path->getPointNumber()) { + if (RCMGetCourse()->getCrsData()->getPathData(mObj->mPathID)->isClosed()) { + pointIdx = 0; + } else { + pointIdx = getPointIndex() - 1; + mDirection = -1; + } + } else if (pointIdx < 0) { + pointIdx = getPointIndex() + 1; + mDirection = 1; + } + + CrsData::PointData* next = RCMGetCourse()->getCrsData()->getPointData(mObj->mPathID, pointIdx); + + JGeometry::TVec3f nextPos; + nextPos.set(next->pos); + + JGeometry::TVec3f diff; + diff.sub(nextPos, current); + + mDistance = PSVECMag(&diff); + mDistanceDirty = false; + } + + return mDistance; +} + +void TPathUtilInterrupt::reset() { + mDistanceDirty = true; + mDistance = 0.0f; + setPointIndex(0); + mDirection = 1; + _20 = false; +} + +TPathWalk::TPathWalk(const CrsData::SObject *sObject) { + _88 = new TPathUtilInterrupt(sObject); + _4 = new TFreeRotate(); + _8 = new TFreeRotate(); + crsGround = new CrsGround(RCMGetCourse()); + _7c = sObject->position.x; + _80 = sObject->position.y; + _84 = sObject->position.z; +} + +TPathWalk::~TPathWalk() { + delete _88; + delete _4; + delete _8; + delete crsGround; +} + +bool TPathWalk::init(JGeometry::TVec3f *pos, JGeometry::TVec3f *vel, JGeometry::TPos3f *rot) { + _10 = pos; + _18 = rot; + _14 = vel; + PSMTXIdentity(_1c); + PSMTXIdentity(_4c); + _4->init(&_1c); + _8->init(&_4c); + return reset(); +} + +bool TPathWalk::reset() { + bool didUpdate = false; + JGeometry::TVec3f local_28; + + _88->reset(); + _94 = 0; + PSMTXIdentity(_1c); + PSMTXIdentity(_4c); + _18->getYDir(local_28); + _8->setTargetVec(local_28, 1.0f, 1.0f, 1.0f, 'y'); + _8->update(); + _18->getZDir(local_28); + _4->setTargetVec(local_28, 1.0f, 1.0f, 1.0f, 'z'); + didUpdate = _4->update(); + _90 = 0.0f; + _a0 = 0.0f; + _98 = 0.0f; + _a4 = 0.0f; + _9c = 0.0f; + mCheckLength = sNearlyReachTargetLength; + return didUpdate; +} + +void TPathWalk::setParameters(f32 param_1, f32 param_2, f32 param_3, f32 param_4, f32 param_5) { + _90 = param_1; + _98 = param_2; + _9c = param_3; + if (param_4 == 0.0f) { + param_4 = _98; + } + _a0 = param_4; + if (param_5 == 0.0f) { + param_5 = _9c; + } + _a4 = param_5; +} + +void TPathWalk::setCheckLength(f32 checkLength) { + if (checkLength <= 0.0f) { + checkLength = sNearlyReachTargetLength; + } + mCheckLength = checkLength; +} + +s16 TPathWalk::update() { + TPathUtilInterrupt *pathInt; + s16 result = -1; + + if (_94) { + dirUpdate(); + posUpdate(); + + if (checkReachTarget()) { + pathInt = _88; + result = pathInt->getPointIndex(); + + if (pathInt->_20) { + pathInt->_20 = false; + } else { + pathInt->mDistanceDirty = true; + + s16 node = pathInt->getPointIndex(); + node += pathInt->mDirection; + + if (node >= RCMGetCourse()->getCrsData()->getPathData(pathInt->mObj->mPathID)->getPointNumber()) { + if (RCMGetCourse()->getCrsData()->getPathData(pathInt->mObj->mPathID)->isClosed()) { + node = 0; + } else { + node = pathInt->getPointIndex() - 1; + pathInt->mDirection = -1; + } + } else if (node < 0) { + node = pathInt->getPointIndex() + 1; + pathInt->mDirection = 1; + } + + pathInt->setPointIndex(node); + } + } + } + + return result; +} + +void TPathWalk::dirUpdate() { + JGeometry::TVec3f crsPointNormal; + + _4->update(); + _8->update(); + PSMTXConcat(_4c, _1c, *_18); + + if (!_4->_28) { + if (_88->_20) { + crsPointNormal.set(_88->_14); + } else { + CrsData::PointData *pointData = RCMGetCourse()->getCrsData()->getPointData(_88->mObj->mPathID, _88->getPointIndex()); + crsPointNormal.set(pointData->pos); + } + crsPointNormal.sub(*_10); + crsPointNormal.y = 0.0f; + crsPointNormal.normalize(); + _4->setTargetVec(crsPointNormal, _a0, _98, 0.0f, 'z'); + } + if (!_8->_28) { + crsGround->search(*_10); + JGeometry::TVec3f crsGroundNormal; + crsGround->getNormal(&crsGroundNormal); + crsGroundNormal.x = 0.0f; + crsGroundNormal.normalize(); + _8->setTargetVec(crsGroundNormal, _a4, _9c, 0.0f, 'y'); + } +} + +void TPathWalk::posUpdate() { + JGeometry::TVec3f zDir; + _18->getZDir(zDir); + f32 initialHeight = _10->y; + zDir.normalize(); + zDir.scale(_90); + _14->set(zDir); + _10->add(*_14); + + JGeometry::TVec3f crsGroundNormal; + crsGround->search(*_10); + crsGround->getNormal(&crsGroundNormal); + if (crsGround->getAttribute() == CrsGround::Attr_255) { + _10->y = initialHeight; + } else { + _10->y = crsGround->getHeight(); + } + return; +} + +bool TPathWalk::checkReachTarget() { + bool reached = false; + JGeometry::TVec3f target; + + if (_88->_20) { + target.set(_88->_14); + } else { + CrsData::PointData *point = RCMGetCourse()->getCrsData()->getPointData(_88->mObj->mPathID, _88->getPointIndex()); + target.set(point->pos); + } + + target.sub(*_10); + target.y = 0.0f; + + if (target.squared() < mCheckLength * mCheckLength) { + reached = true; + } + + return reached; +} + +void TPathWalk::forceTurn(const JGeometry::TVec3f ¶m_1) { + _4->setTargetVec(param_1, 1.0f, 1.0f, 1.0f, 'z'); + dirUpdate(); +} + +void TPathWalk::forceTurn(const JGeometry::TVec3f ¶m_1, const JGeometry::TVec3f ¶m_2) { + _8->setTargetVec(param_1, 1.0f, 1.0f, 1.0f, 'y'); + _4->setTargetVec(param_2, 1.0f, 1.0f, 1.0f, 'z'); + dirUpdate(); +} + +TFreeFly::TFreeFly() { + mFreeRotate = nullptr; + mPosition = nullptr; + mVelocity = nullptr; + _10 = nullptr; + mFreeRotate = new TFreeRotate(); +} + +TFreeFly::~TFreeFly() { + delete mFreeRotate; +} + +void TFreeFly::init(JGeometry::TVec3f *param_1, JGeometry::TVec3f *param_2, JGeometry::TPos3f *param_3) { + mPosition = param_1; + _10 = param_3; + mVelocity = param_2; + PSMTXIdentity(_14); + mFreeRotate->init(&_14); +} + +void TFreeFly::reset() { + _54 = 0; +} + +void TFreeFly::setParameters(f32 param_1, f32 param_2, f32 param_3) { + mSpeed = param_1; + _58 = param_2; + _5c = param_3; +} + +u8 TFreeFly::update() { + if (_54 != 0) { + if (checkReachTarget()) { + _54 = 0; + } else { + dirUpdate(); + posUpdate(); + } + } + return _54; +} + +void TFreeFly::dirUpdate() { + JGeometry::TVec3f local_38; + mFreeRotate->update(); + PSMTXCopy(_14, *_10); + if (mFreeRotate->_28 == false) { + local_38.sub(_44, *mPosition); + local_38.y = 0.0f; + local_38.normalize(); + mFreeRotate->setTargetVec(local_38, _5c, _58, 0.0f, 'z'); + } +} + +void TFreeFly::posUpdate() { + JGeometry::TVec3f moveDir; + JGeometry::TVec3f dir; + + dir.sub(_44, *mPosition); + dir.normalize(); + + _10->getZDir(moveDir); + moveDir.normalize(); + + moveDir.y = dir.y; + + moveDir.normalize(); + moveDir.scale(mSpeed); + + mVelocity->set(moveDir); + mPosition->add(*mVelocity); +} + +bool TFreeFly::checkReachTarget() { + bool reached = false; + JGeometry::TVec3f delta; + delta.sub(_44, *mPosition); + + if (delta.squared() < sNearlyReachTargetLength * sNearlyReachTargetLength) { + reached = true; + } + return reached; +} + +TFreeFall::TFreeFall() {} + +TFreeFall::TFreeFall(JGeometry::TVec3f *pos, JGeometry::TVec3f *vel, JGeometry::TPos3f *rot) { + init(pos, vel, rot); +} + +TFreeFall::~TFreeFall() {} + +void TFreeFall::init(JGeometry::TVec3f *pos, JGeometry::TVec3f *vel, JGeometry::TPos3f *mtx) { + #line 561 + JUT_ASSERT(pos != 0); + #line 562 + JUT_ASSERT(vel != 0); + #line 563 + JUT_ASSERT(mtx != 0); + mPos = pos; + mVel = vel; + mRot = mtx; +} + +void TFreeFall::reset() { + _4 = 0.99f; + _8 = 1.0f; + _c = 0.3f; + _10 = 1.0f; + mRotSpeed = 0.95f; + mGravity = 50.0f; + mEnabled = false; +} + +bool TFreeFall::update() { + if (mEnabled) { + roll(); + } + return mEnabled; +} + +void TFreeFall::roll() { + JGeometry::TVec3f pos; + JGeometry::TVec3f gravity; + + pos.set(*mPos); + mVel->scale(_4); + getGravity(&gravity); + addAccel(gravity); + mPos->add(*mVel); + reflect(pos); + rotate(); +} + +void TFreeFall::reflect(const JGeometry::TVec3f ¶m_1) { + JGeometry::TVec3f local_94; + JGeometry::TVec3f local_a0; + JGeometry::TVec3f local_ac; + JGeometry::TVec3f local_b8; + + CrsGround crsGround(RCMGetCourse()); + crsGround.search(*mPos, param_1); + + u32 attr = crsGround.getAttribute(); + if ((attr == CrsGround::Attr_2) || (attr != CrsGround::Attr_10 && (mPos->y < mGravity + crsGround.getHeight()))) { + if (attr == CrsGround::Attr_2) { + f32 wallNormal = crsGround.getWallNormal(&local_94, nullptr); + local_a0.set(local_94); + local_a0.normalize(wallNormal); + mPos->add(local_a0); + } else { + crsGround.getNormal(&local_94); + mPos->y = mGravity + crsGround.getHeight(); + mVel->scale(_8); + } + + local_ac.scale(local_94.dot(*mVel), local_94); + + if (PSVECMag(&local_ac) > _c) { + getReflect(local_94, &local_b8); + } else { + local_b8.zero(); + } + + local_ac.scale(-(_10 + 1.0f)); + local_ac.add(local_b8); + mVel->add(local_ac); + } +} + +void TFreeFall::getReflect(const JGeometry::TVec3f ¶m_1, JGeometry::TVec3f *param_2) { + JGeometry::TVec3f local_6c; + JGeometry::TVec3f local_78; + + local_78.set(*mVel); + local_78.normalize(); + + local_6c.cross(param_1, local_78); + local_6c.normalize(); + + local_78.cross(local_6c, param_1); + local_78.normalize(); + + if (local_78.isZero()) { + local_78.set(0.0f, 0.0f, 1.0f); + } + param_2->set(local_78); +} + +void TFreeFall::rotate() { + JGeometry::TPos3f local_78; + JGeometry::TVec3f local_84; + JGeometry::TVec3f local_90; + JGeometry::TVec3f local_9c; + JGeometry::TVec3f local_a8; + + local_84.set(mVel->x, 0.0f, mVel->z); + if (!local_84.isZero()) { + f32 dVar4 = mRotSpeed * SiUtil::getNormalRange(local_84.length(), 0.0f, 50.0f); + local_a8.set(*mVel); + local_a8.normalize(); + local_9c.set(0.0f, 1.0f, 0.0f); + local_90.cross(local_9c, local_a8); + local_90.normalize(); + local_78[2][3] = 0.0f; + local_78[1][3] = 0.0f; + local_78[0][3] = 0.0f; + local_78[2][2] = 0.0f; + local_78[1][2] = 0.0f; + local_78[0][2] = 0.0f; + local_78[2][1] = 0.0f; + local_78[1][1] = 0.0f; + local_78[0][1] = 0.0f; + local_78[2][0] = 0.0f; + local_78[1][0] = 0.0f; + local_78[0][0] = 0.0f; + local_78.setRotate(local_90, dVar4); + PSMTXConcat(local_78, *mRot, *mRot); + } +} + +void TFreeFall::addAccel(const JGeometry::TVec3f &accel) { + JGeometry::TVec3f newAccel; + JGeometry::TVec3f crsNormal; + + CrsGround crsGround(RCMGetCourse()); + crsGround.search(*mPos); + if (mPos->y - accel.y < mGravity + crsGround.getHeight()) { + crsGround.getNormal(&crsNormal); + f32 dp = crsNormal.dot(accel); + JMAVECScaleAdd(&crsNormal, &accel, &newAccel, -dp); + mVel->add(newAccel); + } else { + mVel->add(accel); + } +} + +void TFreeFall::getGravity(JGeometry::TVec3f *gravity) { + gravity->set(0.0f, -1.0f, 0.0f); + gravity->scale(_c); +} + +void TFreeFallShakeSky::getGravity(JGeometry::TVec3f *gravity) { + gravity->set(*RCMGetCourse()->getDirY()); + gravity->normalize(); + gravity->negate(); + gravity->scale(_c); +} + +void TFreeFallShakeSky::reset() { + TFreeFall::reset(); + _34 = 5.0f; + _38 = 0; + _30 = 0.0f; + mRnd = nullptr; +} + +void TFreeFallShakeSky::getReflect(const JGeometry::TVec3f ¶m_1, JGeometry::TVec3f *param_2) { + JGeometry::TVec3f local_6c; + JGeometry::TVec3f local_78; + local_78.set(*mVel); + local_78.normalize(); + local_6c.cross(param_1, local_78); + local_6c.normalize(); + local_78.cross(local_6c, param_1); + local_78.normalize(); + if (local_78.isZero()) { + local_78.set(0.0f, 0.0f, 1.0f); + } + param_2->set(local_78); +} + +// FIX: Register mismatch around `local_48.normalize();`. +void TFreeFallShakeSky::reflect(const JGeometry::TVec3f ¶m_1) { + JGeometry::TVec3f local_48; + JGeometry::TVec3f local_3c; + JGeometry::TVec3f local_30; + JGeometry::TVec3f local_24; + + CrsGround crsGround(RCMGetCourse()); + crsGround.search(*mPos, param_1); + + u32 attr = crsGround.getAttribute(); + f32 f25 = 0.0f; + + if (attr == CrsGround::Attr_2 || (attr != CrsGround::Attr_10 && mPos->y < mGravity + crsGround.getHeight())) { + local_48.set(0.0f, 0.0f, 0.0f); + if (attr == CrsGround::Attr_2) { + f25 = crsGround.getWallNormal(&local_48, nullptr); + crsGround.getWallNormal(&local_48, nullptr); + + if (_38 != 0) { + _30 = 0.0f; + } + } else { + crsGround.getNormal(&local_48); + f32 height = crsGround.getHeight(); + + f25 = (mGravity + height) - mPos->y; + mVel->scale(_8); + + if (_38 != 0 && _30 > F_HALF_PI) { + if (mRnd != nullptr) { + + local_24.set(*mVel); + local_24.normalize(); + + local_30.set(0.0f, 1.0f, 0.0f); + local_3c.cross(local_30, local_24); + local_3c.normalize(); + + f32 velMag = mVel->length(); + f32 minLen = (5.0f < velMag) ? 5.0f : velMag; + + f32 scaledRand = (2.0f * mRnd->get_ufloat_1()) - 1.0f; + + f32 f24 = minLen * scaledRand; + local_3c.scale(f24); + mVel->add(local_3c); + } + + mVel->y += (_34 * SiUtil::getNormalRange(mVel->length(), 5.0f, 20.0f) + 1.0f); + _30 = 0.0f; + } + } + + mVel->length(); + local_48.normalize(); + + JGeometry::TVec3f local_18; + local_18.scale(local_48.dot(*mVel), local_48); + + JGeometry::TVec3f local_0c; + local_0c.scale(-(1.0f + _10), local_18); + mVel->add(local_0c); + + local_18.scale(f25, local_48); + mPos->add(local_18); + + } else if (_38 != 0) { + _30 = 0.0f; + } +} + +void TFreeFallShakeSky::rotate() { + JGeometry::TPos3f local_78; + JGeometry::TVec3f local_84; + JGeometry::TVec3f local_90; + JGeometry::TVec3f local_9c; + JGeometry::TVec3f local_a8; + + local_84.set(mVel->x, 0.0f, mVel->z); + if (!local_84.isZero()) { + f32 dVar5 = mRotSpeed * SiUtil::getNormalRange(local_84.length(), 0.0f, 50.0f); + local_a8.set(*mVel); + local_a8.normalize(); + + local_9c.set(0.0f, 1.0f, 0.0f); + local_90.cross(local_9c, local_a8); + local_90.normalize(); + + // is there a zeroing function? + local_78[2][3] = 0.0f; + local_78[1][3] = 0.0f; + local_78[0][3] = 0.0f; + local_78[2][2] = 0.0f; + local_78[1][2] = 0.0f; + local_78[0][2] = 0.0f; + local_78[2][1] = 0.0f; + local_78[1][1] = 0.0f; + local_78[0][1] = 0.0f; + local_78[2][0] = 0.0f; + local_78[1][0] = 0.0f; + local_78[0][0] = 0.0f; + + local_78.setRotate(local_90, dVar5); + PSMTXConcat(local_78.mMtx, mRot->mMtx, mRot->mMtx); + _30 += dVar5; + } +} + +TFreeFallShakeSky::~TFreeFallShakeSky() {} + + +void TPathUtilInterrupt::getCurrentNodePos(JGeometry::TVec3f *) {} + +void TPathUtilInterrupt::getNextNodePos(JGeometry::TVec3f *) {} + +void TPathUtilInterrupt::updateNode() {} + + +TFreeFallDonkyRock::~TFreeFallDonkyRock() {} + +void TFreeFallDonkyRock::reflect(const JGeometry::TVec3f &) {} + +void TFreeFallDonkyRock::reset() {} + +void TFreeFallDonkyRock::getReflect(const JGeometry::TVec3f &, JGeometry::TVec3f *) {} + + +#include "JSystem/JAudio/JASFakeMatch2.h" From fe401d2b1bf83675843344f7fc068a895a8ff33e Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 00:33:28 +1000 Subject: [PATCH 13/29] GeoObjMgr - Implement majority of MapObjSkyShip. This includes classes `TMapObjSkyShip`, `TMapObjPathYoshiHeli`, `TMapObjMashBalloon` and `TMapObjUFO`. There is only one minor mismatch with `TMapObjUFO::initFunc_Wait()`. --- include/Shiraiwa/Objects/MapObjSkyShip.h | 119 +++++++ src/Sato/GeographyObjMgr.cpp | 10 +- src/Shiraiwa/MapObjSkyShip.cpp | 388 +++++++++++++++++++++++ 3 files changed, 512 insertions(+), 5 deletions(-) create mode 100644 include/Shiraiwa/Objects/MapObjSkyShip.h diff --git a/include/Shiraiwa/Objects/MapObjSkyShip.h b/include/Shiraiwa/Objects/MapObjSkyShip.h new file mode 100644 index 00000000..7dd7b978 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjSkyShip.h @@ -0,0 +1,119 @@ +#ifndef MAPOBJSKYSHIP_H +#define MAPOBJSKYSHIP_H + +#include "JSystem/J3D/J3DAnmTextureSRTKey.h" +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Osako/shadowModel.h" +#include "Sato/J3DAnmObject.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Coord3D.h" +#include "Shiraiwa/Coord3DUtil.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + + +class TMapObjSkyShip : public TMapObjHioNode { +public: + TMapObjSkyShip(const CrsData::SObject &sObject); // 0x80298b48 + virtual ~TMapObjSkyShip(); // 0x80298c30 + virtual ShadowModel::ShadowKind getShadowKind() const { // 0x8029a3dc + return ShadowModel::cShadowKind_SkyShip; + } + virtual void reset(); // 0x80298d04 + virtual void calc(); // 0x80298f60 + virtual const char *getBmdFileName(); // 0x80298f10 + virtual const char *getShadowBmdFileName(); // 0x80298f38 + virtual void createColModel(J3DModelData *) {} // 0x8029a3d8 + virtual f32 getAmplitude() { return sAmplitude; } // 0x80299258 + virtual s16 getAmpTimer() { return sAmpTimer; } // 0x80299260 + void moveShadowRot(); // 0x802990bc + void getNodeDir(u16, JGeometry::TVec3f *); // 0x80299170 + void localMove(); // 0x802991cc + + + static f32 sAmplitude; // 0x80415198 + static s16 sAmpTimer; // 0x8041519c + +public: + u16 _14c; // 0x14c + s16 _14e; // 0x14e - unused? + f32 _150; // 0x150 + f32 _154; // 0x154 + TPathMove *mPathMove; // 0x158 + TFreeRotate *mFreeRotate; // 0x15c +}; // 0x160 + + +class TMapObjPathYoshiHeli : public TMapObjSkyShip { +public: + TMapObjPathYoshiHeli(const CrsData::SObject &sObject) : TMapObjSkyShip(sObject) { + createSoundMgr(); + } + virtual ~TMapObjPathYoshiHeli() {} // 0x8029a3e4 + virtual void loadAnimation(); // 0x802999c4 + virtual void createModel(JKRSolidHeap *, u32); // 0x80299a0c + virtual void reset(); // 0x80299268 + virtual void calc(); // 0x802994b0 + virtual void update(); // 0x80299980 + virtual const char *getBmdFileName() { return "/Objects/YoshiHeliB.bmd"; } // 0x8029a508 + virtual const char *getShadowBmdFileName() { return NULL; } // 0x8029a514 + virtual f32 getAmplitude() { return sAmplitude; } // 0x8029a51c + virtual s16 getAmpTimer() { return sAmpTimer; } // 0x8029a524 + void aimVelDir(); // 0x80299538 + + static f32 sAmplitude; // 0x804151a0 + static s16 sAmpTimer; // 0x804151a4 + static f32 sReachDistance; + static J3DAnmTextureSRTKey *sPathYoshiHeliBtkAnm; + +private: + J3DAnmObjMaterial mAnmObjMaterial; // 0x160 +}; // 0x180 + + +class TMapObjMashBalloon : public TMapObjSkyShip { +public: + TMapObjMashBalloon(const CrsData::SObject &sObject) : TMapObjSkyShip(sObject) {} + virtual ~TMapObjMashBalloon() {} // 0x8029a2cc + virtual void reset(); // 0x80299a48 + virtual const char *getBmdFileName() { return "/Objects/mash_balloon.bmd"; } // 0x8029a3b0 + virtual const char *getShadowBmdFileName() { return "/Objects/mash_balloon_shadow.bmd"; } // 0x8029a3bc + virtual f32 getAmplitude() { return sAmplitude; } // 0x8029a3c8 + virtual s16 getAmpTimer() { return sAmpTimer; } // 0x8029a3d0 + + static f32 sAmplitude; // 0x804151ac + static s16 sAmpTimer; // 0x804151b0 + +private: + JGeometry::TPos3f _160; // 0x160 - mRotMtx Rotation Matrix copy? +}; // 0x190 + + +class TMapObjUFO : public TMapObjHioNode, StateObserver { +public: + TMapObjUFO(const CrsData::SObject &sObject); + virtual ~TMapObjUFO(); // 0x80299c9c + virtual void reset(); // 0x80299dac + virtual void calc(); // 0x80299f68 + virtual const char *getBmdFileName() { return "/Objects/ufo.bmd"; } // 0x8029a2c0 + virtual void createColModel(J3DModelData *) {} // 0x8029a2bc + virtual void MoveExec(); // 0x80299efc + virtual void InitExec(); // 0x80299e90 + void initFunc_Fly(); // 0x80299fc4 + void doFunc_Fly(); // 0x8029a128 + void initFunc_Wait(); // 0x8029a224 + void doFunc_Wait(); // 0x8029a284 + + static f32 sRotRad; + static f32 sFlySpeed; + static s16 sWaitFrame; + static StateFuncSet sTable[2]; + +private: + TPathUtil *mPathUtil; // 0x158 + JGeometry::TPos3f _15c; // 0x15c +}; // 0x18c + +#endif // MAPOBJSKYSHIP_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 272d6be8..67c56a28 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -46,6 +46,7 @@ #include "Shiraiwa/Objects/MapObjDonkyTree.h" #include "Shiraiwa/Objects/MapObjDossun.h" #include "Shiraiwa/Objects/MapObjPool.h" +#include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjWanwan.h" #include "Sato/GeographyObjMgr.h" @@ -103,7 +104,7 @@ GEO_OBJ_NEW(GeoCannon); GEO_OBJ_NEW(TMapObjWanwan); GEO_OBJ_NEW_S(TMapObjWanwanChain); GEO_OBJ_NEW_S(TMapObjWanwanPile); -// GEO_OBJ_NEW(TMapObjSkyShip); +GEO_OBJ_NEW(TMapObjSkyShip); GEO_OBJ_NEW_S(TMapObjDonkyRock); GEO_OBJ_NEW(TMapObjDonkyTree); GEO_OBJ_NEW(GeoDkCloud); @@ -187,11 +188,10 @@ GEO_OBJ_NEW(TMapObjDesertTree); // GEO_OBJ_NEW(TMapObjWluSearchLight); // GEO_OBJ_NEW(TMapObjVentilator); // GEO_OBJ_NEW_S(TShineArrow); -// GEO_OBJ_NEW(TMapObjUFO); -// GEO_OBJ_NEW(TMapObjMashBalloon); -// GEO_OBJ_NEW(TMapObjPathYoshiHeli); +GEO_OBJ_NEW(TMapObjUFO); +GEO_OBJ_NEW(TMapObjMashBalloon); +GEO_OBJ_NEW(TMapObjPathYoshiHeli); // GEO_OBJ_NEW(TMapObjFireBall); -// GEO_OBJ_NEW(TMapObjUFO); GEO_OBJ_NEW_S(GeoWaterDown); GEO_OBJ_NEW_S(GeoWaterMiddleD); GEO_OBJ_NEW(TMapObjDonkyRockGen); diff --git a/src/Shiraiwa/MapObjSkyShip.cpp b/src/Shiraiwa/MapObjSkyShip.cpp index e69de29b..e151bfb1 100644 --- a/src/Shiraiwa/MapObjSkyShip.cpp +++ b/src/Shiraiwa/MapObjSkyShip.cpp @@ -0,0 +1,388 @@ +#include "Shiraiwa/Objects/MapObjSkyShip.h" +#include "JSystem/J3D/J3DAnmTextureSRTKey.h" +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JMath/JMath.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/RaceMgr.h" +#include "Osako/shadowModel.h" +#include "Sato/GeographyObj.h" +#include "Sato/ObjUtility.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Coord3D.h" +#include "Shiraiwa/Coord3DUtil.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "dolphin/mtx.h" +#include "math.h" + +StateObserver::StateFuncSet TMapObjUFO::sTable[2] = { + { 0, &TMapObjUFO::initFunc_Fly, &TMapObjUFO::doFunc_Fly }, + { 1, &TMapObjUFO::initFunc_Wait, &TMapObjUFO::doFunc_Wait }, +}; + +J3DAnmTextureSRTKey *TMapObjPathYoshiHeli::sPathYoshiHeliBtkAnm; + +f32 TMapObjSkyShip::sAmplitude = 300.0f; +s16 TMapObjSkyShip::sAmpTimer = 100; +f32 TMapObjPathYoshiHeli::sAmplitude = 5.0f; +s16 TMapObjPathYoshiHeli::sAmpTimer = 7000; +f32 TMapObjPathYoshiHeli::sReachDistance = 1000.0f; +f32 TMapObjMashBalloon::sAmplitude = 500.0f; +s16 TMapObjMashBalloon::sAmpTimer = 100; +f32 TMapObjUFO::sRotRad = 0.06; +f32 TMapObjUFO::sFlySpeed = 500.0f; +s16 TMapObjUFO::sWaitFrame = 120; + +TMapObjSkyShip::TMapObjSkyShip(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { +#line 28 + JUT_ASSERT_MSG(mObjData->mPathID != 0xffff, "TMapObjSkyShip: Illegal Path ID"); + setObjFlagSimpleDraw(); + mPathMove = new TPathMove(&sObject); + mFreeRotate = new TFreeRotate(); +} + +TMapObjSkyShip::~TMapObjSkyShip() { + delete mPathMove; + delete mFreeRotate; +} + +void TMapObjSkyShip::reset() { + GeographyObj::resetObject(); + clrObjFlagCheckGeoHitting(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + _58 = 0; + + f32 speed = mObjData->mParam1 * 0.01f; + if (speed == 0.0f) { + speed = 10.0f; + } + + if (mObjData->mPathID != 0xffff) { + mPathMove->getNodePosition(&mPos, 0); + TPathMove *pathMove = mPathMove; + pathMove->_14 = speed; + pathMove->_18 = speed; + pathMove->_20 = (speed * 0.5f) * (speed * 0.5f); + mPathMove->init(&mPos, &mVel); + mFreeRotate->init(&mRotMtx); + + JGeometry::TVec3f nodeDir; + getNodeDir(mPathMove->getNextNode(), &nodeDir); + nodeDir.normalize(); + + mRotMtx.setZDir(nodeDir); + mFreeRotate->setTargetVec(nodeDir, 1.0f, 1.0f, 0.0f, 'z'); + mPathMove->setTargetNode(); + mVel.zero(); + } + + f32 yPos = mPos.y; + _154 = yPos; + _150 = yPos; + _14c = 0; +} + +const char *TMapObjSkyShip::getBmdFileName() { + static const char *cBmdName = "/Objects/SkyShip1.bmd"; + return cBmdName; +} + +const char *TMapObjSkyShip::getShadowBmdFileName() { + static const char *cShadowBmdName = "/Objects/SkyShip1Shadow.bmd"; + return cShadowBmdName; +} + +void TMapObjSkyShip::calc() { + if (mObjData->mPathID != 0xffff) { + mPos.y = _154; + if (!mPathMove->update()) { + JGeometry::TVec3f nodeDir; + getNodeDir(mPathMove->getNextNode(), &nodeDir); + + f32 fVar1 = 10.0f / nodeDir.length(); + nodeDir.normalize(); + mFreeRotate->setTargetVec(nodeDir, fVar1, fVar1, 0.0f, 'z'); + mPathMove->setTargetNode(); + } + mFreeRotate->update(); + _154 = mPos.y; + } + localMove(); + moveShadowRot(); +} + +void TMapObjSkyShip::moveShadowRot() { + if (mShadowMdl == nullptr) { + return; + } + + if (mShadowMdl->isInvisibleAll()) { + return; + } + + CrsGround ground(RCMGetCourse()); + ground.search(mPos); + + JGeometry::TPos3f newRotMtx; + PSMTXCopy(mRotMtx, newRotMtx); + + // Surprising this doesn't use mtx.setTrans(); + newRotMtx[0][3] = mPos.x; + newRotMtx[1][3] = ground.getHeight(); + newRotMtx[2][3] = mPos.z; + + mShadowMdl->setBaseTRMtx(newRotMtx); + mShadowMdl->getModel()->setBaseScale(mScale); +} + +void TMapObjSkyShip::getNodeDir(u16 param_1, JGeometry::TVec3f *dir) { + JGeometry::TVec3f nodePos; + mPathMove->getNodePosition(&nodePos, param_1); + dir->sub(nodePos, mPos); +} + +void TMapObjSkyShip::localMove() { + f32 offset = getAmplitude() * JMASSin(_14c); + mPos.y = _150 + offset; + _14c += getAmpTimer(); +} + +void TMapObjPathYoshiHeli::reset() { + GeographyObj::resetObject(); + clrObjFlagCheckGeoHitting(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + _58 = 0; + + f32 speed = mObjData->mParam1 * 0.01f; + if (speed == 0.0f) { + speed = 10.0f; + } + + if (mObjData->mPathID != 0xffff) { + mPathMove->getNodePosition(&mPos, 0); + TPathMove *pathMove = mPathMove; + pathMove->_14 = speed * 0.01f; + pathMove->_18 = speed; + pathMove->_20 = (speed * 0.5f) * (speed * 0.5f); + mPathMove->_20 = sReachDistance * sReachDistance; + mPathMove->init(&mPos, &mVel); + + JGeometry::TVec3f nodeDir; + getNodeDir(mPathMove->getNextNode(), &nodeDir); + nodeDir.normalize(); + + mRotMtx.setZDir(nodeDir); + mPathMove->setTargetNode(); + mVel.zero(); + } + + f32 yPos = mPos.y; + _154 = yPos; + _150 = yPos; + _14c = 0; + mAnmObjMaterial.resetFrame(); +} + +void TMapObjPathYoshiHeli::calc() { + if (mObjData->mPathID != 0xffff) { + mPos.y = _154; + if (!mPathMove->update()) { + JGeometry::TVec3f nodePosDiff; + JGeometry::TVec3f nodePos; + mPathMove->getNodePosition(&nodePos, mPathMove->getNextNode()); + nodePosDiff.sub(nodePos, mPos); // HACK: Unused? + mPathMove->setTargetNode(); + } + aimVelDir(); + _154 = mPos.y; + } + localMove(); + moveShadowRot(); + mAnmObjMaterial.update(); +} + +void TMapObjPathYoshiHeli::aimVelDir() { + JGeometry::TVec3f dirX; + JGeometry::TVec3f dirY; + JGeometry::TVec3f dirZ; + + mRotMtx.getXDir(dirX); + mRotMtx.getYDir(dirY); + mRotMtx.getZDir(dirZ); + + if (!mVel.isZero()) { + dirZ.set(mVel); + } + dirZ.y = 0.0f; + + dirZ.normalize(); + if (dirZ.isZero()) { + dirZ.cross(dirX, dirY); + dirZ.normalize(); + } + + dirY.set(0.0f, 1.0f, 0.0f); + dirX.cross(dirY, dirZ); + dirX.normalize(); + mRotMtx.setXYZDir(dirX, dirY, dirZ); +} + +void TMapObjPathYoshiHeli::update() { + mAnmObjMaterial.anmFrameProc(); + GeographyObj::update(); +} + +void TMapObjPathYoshiHeli::loadAnimation() { + J3DModelData *modelData = mModel.getModelData(); + void *ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/YoshiHeliB.btk"); + J3DAnmObjMaterial::setupTexSRTAnmData(&sPathYoshiHeliBtkAnm, modelData, ptrCourseArc); +} + +void TMapObjPathYoshiHeli::createModel(JKRSolidHeap *jkrSolidHeap, u32 p2) { + mAnmObjMaterial.setExModel(&mModel); + mAnmObjMaterial.setAnmBase(sPathYoshiHeliBtkAnm); + mAnmObjMaterial.initFrameCtrl(mAnmObjMaterial.mAnmBase); +} + +void TMapObjMashBalloon::reset() { + GeographyObj::resetObject(); + + clrObjFlagCheckGeoHitting(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + _58 = 0; + _160.set(mRotMtx); + + static f32 sMaxSpeed = 10.0f; + static f32 sAccel = 0.03f; + static f32 sReachDistance = 2000.0f; + + if (mObjData->mPathID != 0xffff) { + mPathMove->getNodePosition(&mPos, 0); + TPathMove *pathMove = mPathMove; + + // This feels really hack-y... why do this with the static + // values declared earlier? + f32 maxSpeed = sMaxSpeed; + f32 halfMaxSpeed = sMaxSpeed * 0.5f; + pathMove->_14 = sAccel; + pathMove->_18 = maxSpeed; + pathMove->_20 = halfMaxSpeed * halfMaxSpeed; + mPathMove->_20 = sReachDistance * sReachDistance; + + mPathMove->init(&mPos, &mVel); + mFreeRotate->init(&_160); + mPathMove->setTargetNode(); + mVel.zero(); + } + + f32 yPos = mPos.y; + _154 = yPos; + _150 = yPos; + _14c = 0; +} + + +TMapObjUFO::TMapObjUFO(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { +#line 475 + JUT_ASSERT_MSG(mObjData->mPathID != 0xffff, "TMapObjUFO: Illegal Path ID"); + setObjFlagSimpleDraw(); + mPathUtil = new TPathUtil(&sObject); + createSoundMgr(); +} + +TMapObjUFO::~TMapObjUFO() { + delete mPathUtil; +} + +TPathUtil::~TPathUtil() {} + +void TMapObjUFO::reset() { + GeographyObj::resetObject(); + + clrObjFlagCheckGeoHitting(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + clrObjFlagHidding(); + _58 = 0; + PSMTXIdentity(_15c); + + const f32 angle = sRotRad; + const f32 s = sinf(angle); + const f32 c = cosf(angle); + _15c[1][1] = 1.0f; + _15c[0][0] = c; + _15c[0][2] = s; + _15c[2][0] = -s; + _15c[2][2] = c; + _15c[2][1] = 0.0f; + _15c[1][2] = 0.0f; + _15c[1][0] = 0.0f; + _15c[0][1] = 0.0f; + + mPathUtil->reset(); +} + +void TMapObjUFO::InitExec() { Observer_FindAndInit(TMapObjUFO, 2); } + +void TMapObjUFO::MoveExec() { Observer_FindAndExec(TMapObjUFO, 2); } + +void TMapObjUFO::calc() { + ExecuteState(); + PSMTXConcat(mRotMtx, _15c, mRotMtx); + getSoundMgr()->setSe(0x40081); +} + +void TMapObjUFO::initFunc_Fly() { + TPathUtil *pathUtil = mPathUtil; + pathUtil->mDistanceDirty = true; + pathUtil->setPointIndex(pathUtil->getNextNode()); + + CrsData::PointData *point = RCMGetCourse()->getCrsData()->getPointData(mPathUtil->mObj->mPathID, mPathUtil->getPointIndex()); + + JGeometry::TVec3f target; + target.set(point->pos); + + JGeometry::TVec3f dir; + dir.sub(target, mPos); + dir.normalize(); + mVel.scale(sFlySpeed, dir); +} + +void TMapObjUFO::doFunc_Fly() { + mPos.add(mVel); + TPathUtil *pathUtil = mPathUtil; + + CrsData::PointData *pointData = RCMGetCourse()->getCrsData()->getPointData(pathUtil->mObj->mPathID, pathUtil->getPointIndex()); + + JGeometry::TVec3f target; + target.set(pointData->pos); + + JGeometry::TVec3f diff; + diff.sub(target, mPos); + + if (diff.dot(mVel) <= 0.0f) { + mPos.set(target); + setState(1); + } + getSoundMgr()->setSe(0x40080); +} + +// FIX: Something strange about function order. Call is structured the same as other +// functions, so why is it not matching? +void TMapObjUFO::initFunc_Wait() { + if (RCMGetCourse()->getCrsData()->getPointData(mObjData->mPathID, mPathUtil->getPointIndex())->linkPoint == 0) { + setState(0); + } +} + +void TMapObjUFO::doFunc_Wait() { + if (getStateCount() > sWaitFrame) { + setState(0); + } +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From d47296832908c5ebc1449b69faed59464c93fd1d Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 01:20:09 +1000 Subject: [PATCH 14/29] Update TKartThrower's class definition with `sObject` parameter - required by MapObjGeyser to pass onto `TMapObjHioNode` and, subsequently, `GeographyObj`. --- include/Shiraiwa/TKartThrower.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Shiraiwa/TKartThrower.h b/include/Shiraiwa/TKartThrower.h index 0846c42a..606206cb 100644 --- a/include/Shiraiwa/TKartThrower.h +++ b/include/Shiraiwa/TKartThrower.h @@ -7,6 +7,7 @@ class TKartThrower : public TMapObjHioNode { public: + TKartThrower(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) {} virtual ~TKartThrower() {} virtual void getThrowDir(JGeometry::TVec3f* dst, s16); From 8a7576f78289b13ca283c8ae4426fd39be00e07e Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 01:21:44 +1000 Subject: [PATCH 15/29] GeoObjMgr - Implement MapObjGeyser. A few function offsets are wrong, but each function matches otherwise. --- include/Shiraiwa/Objects/MapObjGeyser.h | 97 +++++ src/Sato/GeographyObjMgr.cpp | 5 +- src/Shiraiwa/MapObjGeyser.cpp | 474 ++++++++++++++++++++++++ 3 files changed, 574 insertions(+), 2 deletions(-) create mode 100644 include/Shiraiwa/Objects/MapObjGeyser.h diff --git a/include/Shiraiwa/Objects/MapObjGeyser.h b/include/Shiraiwa/Objects/MapObjGeyser.h new file mode 100644 index 00000000..0e23dfdb --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjGeyser.h @@ -0,0 +1,97 @@ +#ifndef MAPOBJGEYSER_H +#define MAPOBJGEYSER_H + +#include "JSystem/J3D/J3DAnmTextureSRTKey.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/TKartThrower.h" + + +class TMapObjGeyser : public TKartThrower, public StateObserver { +public: + TMapObjGeyser(const CrsData::SObject &); // 0x802a8f6c + virtual ~TMapObjGeyser(); // 0x802a906c + virtual void MoveExec(); // 0x802a91d8 + virtual void InitExec(); // 0x802a916c + virtual const char *getBmdFileName(); // 0x802a9244 + virtual void createColModel(J3DModelData *); // 0x802a926c + virtual void createModel(JKRSolidHeap *, u32); // 0x802a92d4 + virtual void loadAnimation(); // 0x802a9364 + virtual void update(); // 0x802a9700 + virtual void reset(); // 0x802a9744 + virtual void calc(); // 0x802a98bc + virtual void viewCalc(u32); // 0x802a996c + virtual void getThrowDir(JGeometry::TVec3f *, s16); // 0x802a9998 + virtual s32 getThrowPow(); // 0x802a9ba4 + virtual void getKartThrowDirPow(JGeometry::TVec3f *, f32 *, int); // 0x802a9bb0 + virtual void getItemThrowDirPow(JGeometry::TVec3f *, f32 *, const ItemObj &); // 0x802a9c34 + virtual bool checkChangeAct(); // 0x802a9f70 + + void playEmitter(u32, const JGeometry::TVec3f &); // 0x802a93c4 + void moveEmitter(u32, const JGeometry::TVec3f &); // 0x802a9564 + void initFunc_Start(); // 0x802a9d7c + void doFunc_Start(); // 0x802a9dec + void initFunc_Wait(); // 0x802a9e74 + void doFunc_Wait(); // 0x802a9ee4 + void initFunc_Act(); // 0x802aa03c + void doFunc_Act(); // 0x802aa080 + void initFunc_JumpUp(); // 0x802aa1c8 + void doFunc_JumpUp(); // 0x802aa294 + void initFunc_JumpStay(); // 0x802aa44c + void doFunc_JumpStay(); // 0x802aa450 + void initFunc_JumpDown(); // 0x802aa608 + void doFunc_JumpDown(); // 0x802aa61c + + static const char *scEffectName[6]; // 0x803a6078 + static TAnmInfo sAnmInfos[4]; // 0x803a6090 + static StateFuncSet sTable[6]; // 0x803a6170 + static s16 sActTime; // 0x80415258 + static f32 sJumpUpStartVel; // 0x8041525c + static u16 sCheckCycle; // 0x80415260 + static s16 sEfctABCDEndFrame; // 0x80415262 + static f32 sBoundHeight; // 0x80415264 + static s16 sEfctEFEndFrame; // 0x80416f00 + static s32 sJointNum; // 0x80416f04 + static J3DAnmTextureSRTKey *sGeyserBtkAnm; // 0x80416f08 + static const s8 sAnmTable[6]; // 0x8041cbd8 + + // MJB - Fabricated: + inline void createEmitter(int); + inline void setAnimation(int); + + // Inline/Unused + JPABaseEmitter *getEmitter(u32 idx) { return _1a0[idx]; } + bool isActiveEmitter(u32 idx) { return _1a0[idx]->checkStatus(1); }; + void stopEmitter(u32 idx) { _1a0[idx]->stopCreateParticle(); } + // void hideEmitter(u32); + void showEmitter(u32 idx) { _1a0[idx]->playCreateParticle(); } + // void getEmitterPos(JGeometry::TVec3f *); + // void changeAllState(u16); + //void sTopStayTime; + //void sLimitUpVel; + //void sGravity; + //void scHeightOffset; + + J3DAnmObjMaterial mAnmObjMaterial; // 0x158 + TAnmPlayer mAnmPlayer; // 0x178 + s32 _190; // 0x190 + s16 _194; // 0x194 + f32 _198; // 0x198 + u16 _19c; // 0x19c + JPABaseEmitter *_1a0[6]; // 0x1a0 + JGeometry::TVec3f _1b8; // 0x1b8 + f32 _1c4; // 0x1c4 +}; + +class TMapObjGeyserSearch : public TMapObjGeyser { +public: + TMapObjGeyserSearch(const CrsData::SObject &sObject) : TMapObjGeyser(sObject) {} + virtual ~TMapObjGeyserSearch() {} + virtual void reset(); + virtual bool checkChangeAct(); + + static u16 sCheckCycle; +}; + +#endif // MAPOBJGEYSER_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 67c56a28..8c7ec0ba 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -45,6 +45,7 @@ #include "Shiraiwa/Objects/MapObjDonkyRockGen.h" #include "Shiraiwa/Objects/MapObjDonkyTree.h" #include "Shiraiwa/Objects/MapObjDossun.h" +#include "Shiraiwa/Objects/MapObjGeyser.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjWanwan.h" @@ -118,8 +119,8 @@ GEO_OBJ_NEW(GeoVision); // GEO_OBJ_NEW_S(TSMAButterfly); // GEO_OBJ_NEW_S(TSMADonkyBird); // GEO_OBJ_NEW_S(TSMAKamome); -// GEO_OBJ_NEW(TMapObjGeyser); -// GEO_OBJ_NEW(TMapObjGeyserSearch); +GEO_OBJ_NEW(TMapObjGeyser); +GEO_OBJ_NEW(TMapObjGeyserSearch); // GEO_OBJ_NEW_S(TTestStrBarrel); // GEO_OBJ_NEW_S(TTestStrItem); // GEO_OBJ_NEW(TMapObjPeachTree); diff --git a/src/Shiraiwa/MapObjGeyser.cpp b/src/Shiraiwa/MapObjGeyser.cpp index e69de29b..8bd58d9b 100644 --- a/src/Shiraiwa/MapObjGeyser.cpp +++ b/src/Shiraiwa/MapObjGeyser.cpp @@ -0,0 +1,474 @@ +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JMath/JMath.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/RaceMgr.h" +#include "Osako/ResMgr.h" +#include "Sato/GeographyObj.h" +#include "Sato/JPEffectMgr.h" +#include "Sato/ObjUtility.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/AnmPlayer.h" +#include "Shiraiwa/SiUtil.h" +#include "dolphin/mtx.h" +#include "types.h" +#include "Shiraiwa/Objects/MapObjGeyser.h" + +s16 TMapObjGeyser::sActTime = 120; +s16 TMapObjGeyser::sEfctEFEndFrame = sActTime - 25; +f32 TMapObjGeyser::sJumpUpStartVel = 100.0f; +u16 TMapObjGeyser::sCheckCycle = 30; +s16 TMapObjGeyser::sEfctABCDEndFrame = 25; +f32 TMapObjGeyser::sBoundHeight = 2900.0f; +static const char *scJointName = "ef_set"; + +s32 TMapObjGeyser::sJointNum; +J3DAnmTextureSRTKey *TMapObjGeyser::sGeyserBtkAnm; + +const char *TMapObjGeyser::scEffectName[6] = { + "mk_kanketsusen_a", + "mk_kanketsusen_b", + "mk_kanketsusen_c", + "mk_kanketsusen_d", + "mk_kanketsusen_e", + "mk_kanketsusen_f" +}; + +TAnmInfo TMapObjGeyser::sAnmInfos[4] = { + {"/Objects/Geyser11.bca", nullptr, nullptr, 0, 0, 1, 255, 0}, + {"/Objects/Geyser12.bca", nullptr, nullptr, 0, 0, 1, 255, 0}, + {"/Objects/Geyser13.bca", nullptr, nullptr, 0, 0, 1, 255, 0}, + {"/Objects/Geyser14.bca", nullptr, nullptr, 0, 0, 1, 255, 0}, +}; + + +StateObserver::StateFuncSet TMapObjGeyser::sTable[6] = { + {0, &TMapObjGeyser::initFunc_Start, &TMapObjGeyser::doFunc_Start}, + {1, &TMapObjGeyser::initFunc_Wait, &TMapObjGeyser::doFunc_Wait}, + {2, &TMapObjGeyser::initFunc_Act, &TMapObjGeyser::doFunc_Act}, + {3, &TMapObjGeyser::initFunc_JumpUp, &TMapObjGeyser::doFunc_JumpUp}, + {4, &TMapObjGeyser::initFunc_JumpStay, &TMapObjGeyser::doFunc_JumpStay}, + {5, &TMapObjGeyser::initFunc_JumpDown, &TMapObjGeyser::doFunc_JumpDown}, +}; + +const s8 TMapObjGeyser::sAnmTable[6] = { + 5, 5, 0, 1, 2, 3 +}; + +inline void TMapObjGeyser::createEmitter(int idx) { + if (getEmitter(idx) == nullptr) { + JPABaseEmitter *emt = JPEffectMgr::getEffectMgr()->createEmt(scEffectName[idx], mPos); + + #line 169 + JUT_ASSERT(emt != 0); + + f32 scale = (mScale.x > mScale.z) ? mScale.x : mScale.z; + + emt->setGlobalScale(scale); + emt->stopCreateParticle(); + + _1a0[idx] = emt; + } +} + +inline void TMapObjGeyser::setAnimation(int idx) { + setState(idx); + // HACK: sAnmTable may have the wrong type based on these casts... + if ((u32)sAnmTable[idx] != 5 && (u32)sAnmTable[idx] != mAnmPlayer.getCurAnmNumber()) { + mAnmPlayer._11 = sAnmTable[idx]; + mAnmPlayer._10 = 1; + mAnmPlayer._e |= 1; + } +} + + +TMapObjGeyser::TMapObjGeyser(const CrsData::SObject &sObject) : TKartThrower(sObject) { + NewAnmCtrl(); + createSoundMgr(); + mAnmPlayer.resetAnimations(sAnmInfos, 4); + _1b8.zero(); +} + +TMapObjGeyser::~TMapObjGeyser() {} + +void TMapObjGeyser::InitExec() { Observer_FindAndInit(TMapObjGeyser, 6); } + +void TMapObjGeyser::MoveExec() { Observer_FindAndExec(TMapObjGeyser, 6); } + +const char *TMapObjGeyser::getBmdFileName() { + static const char *cBmdName = "/Objects/Geyser1.bmd"; + return cBmdName; +} + +void TMapObjGeyser::createColModel(J3DModelData *modelData) { + f32 scaleXZ = mScale.x > mScale.z + ? mScale.x + : mScale.z; + + f32 max = scaleXZ > mScale.y + ? scaleXZ + : mScale.y; + + createBoundsCylinder(modelData, 140.0f * (scaleXZ / max), + sBoundHeight * (mScale.y / max) + ); +} + +void TMapObjGeyser::createModel(JKRSolidHeap *jkrSolidHeap, u32 p2) { + mModel.createDifferedModel(jkrSolidHeap, p2, 0x200, 0); + mAnmPlayer.registAnimations(mAnmCtrl, &mModel, sAnmInfos, 4); + + sJointNum = mModel.getModelData()->getJointName()->getIndex(scJointName); + + mAnmObjMaterial.setExModel(&mModel); + mAnmObjMaterial.setAnmBase(sGeyserBtkAnm); + mAnmObjMaterial.initFrameCtrl(mAnmObjMaterial.getAnmBase()); +} + +void TMapObjGeyser::loadAnimation() { + J3DModelData *modelData = mModel.getModelData(); + TAnmPlayer::loadAnimations(sAnmInfos, 4, modelData, ResMgr::mcArcCourse); + void *ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/Geyser1.btk"); + J3DAnmObjMaterial::setupTexSRTAnmData(&sGeyserBtkAnm, modelData, ptrCourseArc); +} + +void TMapObjGeyser::playEmitter(u32 id, const JGeometry::TVec3f &pos) { + bool valid = true; + + switch (id) { + case 1: + case 3: + case 5: + valid = false; + break; + } + + if (!valid) { + return; + } + + #line 165 + JUT_MINMAX_ASSERT(0, id, 6); + + if (getEmitter(id) == nullptr) { + valid = true; + + switch (id) { + case 1: + case 3: + case 5: + valid = false; + break; + } + + if (valid) { + JPABaseEmitter* emt = JPEffectMgr::getEffectMgr()->createEmt(scEffectName[id], mPos); + + #line 169 + JUT_ASSERT(emt != 0); + + f32 scale = (mScale.x > mScale.z) ? mScale.x : mScale.z; + + emt->setGlobalScale(scale); + emt->stopCreateParticle(); + + _1a0[id] = emt; + } + } + + getEmitter(id)->playCreateParticle(); + moveEmitter(id, pos); +} + +void TMapObjGeyser::moveEmitter(u32 id, const JGeometry::TVec3f &pos) { + bool ok = true; + + switch (id) { + case 1: + case 3: + case 5: + ok = false; + break; + } + + if (!ok) { + return; + } + + #line 165 + JUT_MINMAX_ASSERT(0, id, 6); + + // Create emitter if missing + if (getEmitter(id) == nullptr) { + bool ok = true; + + switch (id) { + case 1: + case 3: + case 5: + ok = false; + break; + } + + if (ok) { + JPABaseEmitter *emt = JPEffectMgr::getEffectMgr()->createEmt(scEffectName[id], mPos); + + #line 169 + JUT_ASSERT(emt != 0); + + f32 scale = (mScale.x > mScale.z) ? mScale.x : mScale.z; + + emt->setGlobalScale(scale); + emt->stopCreateParticle(); + + _1a0[id] = emt; + } + } + + getEmitter(id)->setGlobalTranslation(pos); +} + +void TMapObjGeyser::update() { + mAnmObjMaterial.anmFrameProc(); + GeographyObj::update(); +} + +void TMapObjGeyser::reset() { + GeographyObj::resetObject(); + _58 = 0; + mAnmPlayer.init(mAnmCtrl, sAnmInfos, 4); + mAnmObjMaterial.getFrameCtrl()->reset(); + + _190 = mObjData->mParam1; + if (_190 == 0) { + _190 = 300; + } + + _194 = (mObjData->mParam4 ^ 0x80000000) * 182.04445f; + _198 = mScale.y * 1000.0f; + _19c = 0; + + ResetState(); + + if (RaceMgr::getManager()->getRaceMode() != 1 && mObjData->mParam8 != 0) { + setState(1); + } else { + setState(0); + } + + for (int i = 0; i != 6; i++) { + _1a0[i] = 0; + } + + _1c4 = -sBoundHeight; + _1b8.zero(); +} + +void TMapObjGeyser::calc() { + MtxPtr anmMtx = mModel.getModel()->getAnmMtx(sJointNum); + _1b8.set(anmMtx[0][3], anmMtx[1][3], anmMtx[2][3]); + + ExecuteState(); + mAnmPlayer.update(); + mAnmObjMaterial.getFrameCtrl()->update(); + JGeometry::TVec3f local_18(0.0f, _1c4 + (_1b8.y - mPos.y) / mScale.y, 0.0f); + GeographyObj::setColObjPos(local_18, 0); +} + +void TMapObjGeyser::viewCalc(u32 viewNo) { + mModel.viewCalc(viewNo); +} + +void TMapObjGeyser::getThrowDir(JGeometry::TVec3f *throwDir, s16 kartIdx) { + JGeometry::TVec3f tempThrowDir; + + if (kartIdx == -1) { + tempThrowDir.set(0.0f, 1.0f, 0.0f); + } else { + ObjUtility::getKartVel(kartIdx, &tempThrowDir); + tempThrowDir.y = 0.0f; + if (tempThrowDir.isZero()) { + ObjUtility::getKartZdir(kartIdx, &tempThrowDir); + tempThrowDir.y = 0.0f; + if (tempThrowDir.isZero()) { + tempThrowDir.set(0.0f, 0.0f, 1.0f); + } + } + tempThrowDir.normalize(); + + tempThrowDir.scale(JMASCos(_194)); + tempThrowDir.y = JMASSin(_194); + } + throwDir->set(tempThrowDir); +} + +s32 TMapObjGeyser::getThrowPow() { return mObjData->mParam3; } + +void TMapObjGeyser::getKartThrowDirPow(JGeometry::TVec3f *throwDir, f32 *throwPower, int kartIdx) { + if (throwDir != nullptr) { + getThrowDir(throwDir, kartIdx); + } + if (throwPower != nullptr) { + *throwPower = getThrowPow(); + } +} + +void TMapObjGeyser::getItemThrowDirPow(JGeometry::TVec3f* dir, f32* power, const ItemObj& item) { + JGeometry::TVec3f itemPos; + itemPos.set(item.mPos); + + JGeometry::TVec3f horiz; + horiz.sub(itemPos, mPos); + horiz.y = 0.0f; + horiz.normalize(); + + horiz.scale(JMASCos(_194), horiz); + horiz.y = JMASSin(_194); + + dir->set(horiz); + *power = mObjData->mParam3 * 0.1f; +} + +void TMapObjGeyser::initFunc_Start() { + _58 = 0; + mReaction.setFlg(0, 0); + mReaction.setFlg(6, 0); + mReaction.setFlg(5, 0); + mReaction.setFlg(3, 0); +} + +void TMapObjGeyser::doFunc_Start() { + if (getStateCount() > mObjData->mParam2) { + setAnimation(1); + } +} + +void TMapObjGeyser::initFunc_Wait() { + _58 = 0; + mReaction.setFlg(0, 0); + mReaction.setFlg(6, 0); + mReaction.setFlg(5, 0); + mReaction.setFlg(3, 0); +} + +void TMapObjGeyser::doFunc_Wait() { + // FIX: What inline function/datatype actually exists at 0xa4? + if (checkChangeAct() != 0) { + setAnimation(2); + } +} + +bool TMapObjGeyser::checkChangeAct() { + bool changeAct; + + if (RaceMgr::getManager()->getRaceMode() != 1 && mObjData->mParam8 != 0) { + _19c++; + if (_19c < sCheckCycle) { + changeAct = false; + } else { + _19c = 0; + if (SiUtil::searchNearKartCircle(mPos, mObjData->mParam5) != -1) { + changeAct = true; + } else { + changeAct = false; + } + } + } else { + changeAct = getStateCount() > _190; + } + return changeAct; +} + +void TMapObjGeyser::initFunc_Act() { + playEmitter(4, mPos); + playEmitter(5, mPos); +} + +void TMapObjGeyser::doFunc_Act() { + if (getStateCount() > sActTime) { + setAnimation(3); + } + if (sEfctEFEndFrame == getStateCount()) { + createEmitter(4); + stopEmitter(4); + } +} + +void TMapObjGeyser::initFunc_JumpUp() { + _58 = 0xe; + mReaction.setFlg(0, 3); + mReaction.setFlg(6, 3); + mReaction.setFlg(5, 3); + mReaction.setFlg(3, 3); + mVel.set(0.0f, sJumpUpStartVel * mScale.y, 0.0f); + playEmitter(0, _1b8); + playEmitter(1, _1b8); + playEmitter(2, mPos); + playEmitter(3, mPos); +} + +void TMapObjGeyser::doFunc_JumpUp() { + u8 currentAnmNo = mAnmPlayer.getCurAnmNumber(); + if (mAnmPlayer.mController->getFrameCtrl(currentAnmNo)->checkState(1)) { + setAnimation(4); + } + getSoundMgr()->setSe(0x40047); + createEmitter(0); + getEmitter(0)->setGlobalTranslation(_1b8); +} + +void TMapObjGeyser::initFunc_JumpStay() {} + +void TMapObjGeyser::doFunc_JumpStay() { + u8 currentAnmNo = mAnmPlayer.getCurAnmNumber(); + if (mAnmPlayer.mController->getFrameCtrl(currentAnmNo)->checkState(1)) { + setAnimation(5); + } + getSoundMgr()->setSe(0x40047); + createEmitter(0); + getEmitter(0)->setGlobalTranslation(_1b8); +} + +void TMapObjGeyser::initFunc_JumpDown() { mVel.zero(); } + + + +void TMapObjGeyser::doFunc_JumpDown() { + u8 currentAnmNo = mAnmPlayer.getCurAnmNumber(); + if (mAnmPlayer.mController->getFrameCtrl(currentAnmNo)->checkState(1)) { + setAnimation(1); + } + getSoundMgr()->setSe(0x40047); + createEmitter(0); + getEmitter(0)->setGlobalTranslation(_1b8); + + if (sEfctABCDEndFrame == getStateCount()) { + createEmitter(0); + stopEmitter(0); + createEmitter(2); + stopEmitter(2); + } +} + +void TMapObjGeyserSearch::reset() { + TMapObjGeyser::reset(); + setState(1); + _19c = 0; +} + +u16 TMapObjGeyserSearch::sCheckCycle = 30; +bool TMapObjGeyserSearch::checkChangeAct() { + _19c++; + if (_19c < TMapObjGeyserSearch::sCheckCycle) { + return false; + } + _19c = 0; + f32 radius = mObjData->mParam1; + s16 kartNo = SiUtil::searchNearKartCircle(mPos, radius); + return kartNo != -1; +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From ae4afc32ad6532e8303f39aef46a9aae1d9594c7 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 01:28:12 +1000 Subject: [PATCH 16/29] Implement SmallAnimalGen - used as a base for a few other functions related to creatures in the geography of maps. --- include/Shiraiwa/SmallAnimalGen.h | 38 +++++++++++++++++++++ src/Shiraiwa/SmallAnimalGen.cpp | 57 +++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 include/Shiraiwa/SmallAnimalGen.h diff --git a/include/Shiraiwa/SmallAnimalGen.h b/include/Shiraiwa/SmallAnimalGen.h new file mode 100644 index 00000000..678f67a2 --- /dev/null +++ b/include/Shiraiwa/SmallAnimalGen.h @@ -0,0 +1,38 @@ +#ifndef TSMALLANIMALGEN_H +#define TSMALLANIMALGEN_H + +#include "JSystem/JGeometry/Vec.h" +#include "Kaneshige/Course/CrsData.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + + +class TSmallAnimal : public TMapObjHioNode { +public: + TSmallAnimal(u32 id); + virtual ~TSmallAnimal(); + virtual void reset(); + virtual const char *getBmdFileName() { return NULL; } // 0x802a5e40 + virtual void setOrigin(JGeometry::TVec3f *); // 0x802a5e18 + + JGeometry::TVec3f *mSmallAnimalPos; +}; + + +class TSmallAnimalGen : public TMapObjHioNode { +public: + TSmallAnimalGen(const CrsData::SObject &, u32); // 0x802a5c24 + virtual ~TSmallAnimalGen(); // 0x802a5ca8 + virtual void reset(); // 0x802a5d88 + virtual void calc(); // 0x802a5e3c + void makeObjects(u16); // 0x802a5d8c + + // Inline/Unused + // void getNthObject(unsigned short); + + TSmallAnimal **_14c; // GeographyObj **, maybe? + u16 _150; + u32 _154; +}; + + +#endif // TSMALLANIMALGEN_H diff --git a/src/Shiraiwa/SmallAnimalGen.cpp b/src/Shiraiwa/SmallAnimalGen.cpp index e69de29b..e7072e66 100644 --- a/src/Shiraiwa/SmallAnimalGen.cpp +++ b/src/Shiraiwa/SmallAnimalGen.cpp @@ -0,0 +1,57 @@ +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObjMgr.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "Shiraiwa/SmallAnimalGen.h" + + +TSmallAnimalGen::TSmallAnimalGen(const CrsData::SObject &sObject, u32 id) : TMapObjHioNode(sObject) { + u16 objectCount = sObject.mParam1; + _14c = nullptr; + _150 = 0; + _154 = id; + if (objectCount == 0) { + objectCount = 1; + } + makeObjects((u16)objectCount); +} + +TSmallAnimalGen::~TSmallAnimalGen() { + for (int i = 0; i < _150; i++) { + delete _14c[i]; + } + delete[] _14c; +} + +void TSmallAnimalGen::reset() {} + +void TSmallAnimalGen::calc() {} + +void TSmallAnimalGen::makeObjects(u16 objCount) { + _150 = objCount; + _14c = new TSmallAnimal *[_150]; + + for (int i = 0; i < _150; i++) { + _14c[i] = (TSmallAnimal *)GetGeoObjMgr()->createSubObj(_154); + _14c[i]->setOrigin(&mPos); + } +} + + +TSmallAnimal::TSmallAnimal(u32 id) : TMapObjHioNode(id) { + mSmallAnimalPos = nullptr; + clrAllCheckKartHitFlag(); + clrObjFlagCheckItemHitting(); +} + +TSmallAnimal::~TSmallAnimal() {} + +void TSmallAnimal::reset() { + resetObject(); +} + +void TSmallAnimal::setOrigin(JGeometry::TVec3f *newOrigin) { + mSmallAnimalPos = newOrigin; + mPos.set(*mSmallAnimalPos); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From ca10acd23d5e9869a4da6e0497d23647181e96ec Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 02:26:36 +1000 Subject: [PATCH 17/29] GeoObjMgr - Implement majority of TMapObjSnowRock. Note that `TMapObjSnowRock::hitCheck()` has a register mismatch, probably due to a temporary TVec3f, which I wasn't able to solve. --- include/Shiraiwa/Objects/MapObjSnowRock.h | 66 +++++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/MapObjSnowRock.cpp | 223 ++++++++++++++++++++++ 3 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjSnowRock.h diff --git a/include/Shiraiwa/Objects/MapObjSnowRock.h b/include/Shiraiwa/Objects/MapObjSnowRock.h new file mode 100644 index 00000000..12aef4a1 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjSnowRock.h @@ -0,0 +1,66 @@ +#ifndef MAPOBJSNOWROCK_H +#define MAPOBJSNOWROCK_H + +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JKernel/JKRDisposer.h" +#include "JSystem/JSupport/JSUList.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjSnowRock; + +class TSnowRockSupervisor : public GeoObjSupervisor { +public: + TSnowRockSupervisor() : GeoObjSupervisor() { + _24.initiate(); + } + virtual ~TSnowRockSupervisor() {} + virtual void reset() {} + virtual void calc(); + //void entry(TMapObjSnowRock *); + + JSUList _24; +}; + +class TMapObjSnowRock : public TMapObjHioNode, public StateObserver, JKRDisposer { // Autogenerated +public: + TMapObjSnowRock(const CrsData::SObject &); // 0x802add50 + virtual ~TMapObjSnowRock(); // 0x802ade90 + virtual void MoveExec(); // 0x802adfdc + virtual void InitExec(); // 0x802adf70 + virtual void reset(); // 0x802ae5c0 + virtual void calc(); // 0x802ae678 + virtual const char *getBmdFileName(); // 0x802ae048 + virtual void createColModel(J3DModelData *); // 0x802ae070 + virtual TSnowRockSupervisor *getSupervisor() { return sSupervisor; } + virtual void doKartColCallBack(int); // 0x802ae0d8 + void initFunc_Stand(); // 0x802ae69c + void doFunc_Stand(); // 0x802ae6b0 + void initFunc_Break(); // 0x802aeabc + void doFunc_Break(); // 0x802aebf8 + void initFunc_Die(); // 0x802aec20 + void doFunc_Die(); // 0x802aec30 + void setAttacked(const JGeometry::TVec3f &, f32); // 0x802ae490 + void checkItemHitting(); // 0x802ae7f8 + void makeBreakEmitter(); // 0x802aeb20 + void hitCheck(TMapObjSnowRock *); // 0x802aec34 + + static StateFuncSet sTable[3]; // 0x803a6848 + static f32 sGravity; // 0x804152a0 + static f32 sStartVel; // 0x804152a4 + static TSnowRockSupervisor *sSupervisor; // 0x80416f38 + + // Inline/Unused + + //void JSUList::~JSUList(); + //void JSULink::~JSULink(); + + + JSULink _170; + CrsGround *_180; + f32 _184; +}; // class MapObjSnowRock + +#endif // MAPOBJSNOWROCK_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 8c7ec0ba..10b605a8 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -48,6 +48,7 @@ #include "Shiraiwa/Objects/MapObjGeyser.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" +#include "Shiraiwa/Objects/MapObjSnowRock.h" #include "Shiraiwa/Objects/MapObjWanwan.h" #include "Sato/GeographyObjMgr.h" @@ -124,7 +125,7 @@ GEO_OBJ_NEW(TMapObjGeyserSearch); // GEO_OBJ_NEW_S(TTestStrBarrel); // GEO_OBJ_NEW_S(TTestStrItem); // GEO_OBJ_NEW(TMapObjPeachTree); -// GEO_OBJ_NEW(TMapObjSnowRock); +GEO_OBJ_NEW(TMapObjSnowRock); // GEO_OBJ_NEW(TTestRollObj); // GEO_OBJ_NEW(TMapObjFountain); // GEO_OBJ_NEW(TMapObjHeyho); diff --git a/src/Shiraiwa/MapObjSnowRock.cpp b/src/Shiraiwa/MapObjSnowRock.cpp index e69de29b..475c2ff4 100644 --- a/src/Shiraiwa/MapObjSnowRock.cpp +++ b/src/Shiraiwa/MapObjSnowRock.cpp @@ -0,0 +1,223 @@ +#include "Shiraiwa/Objects/MapObjSnowRock.h" +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "Kaneshige/RaceMgr.h" +#include "Sato/GeographyObj.h" +#include "Sato/ItemObj.h" +#include "Sato/JPEffectMgr.h" +#include "Sato/ObjUtility.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "Shiraiwa/SiUtil.h" +#include "Yamamoto/kartCtrl.h" +#include "types.h" + +StateObserver::StateFuncSet TMapObjSnowRock::sTable[3] = { + 0, &TMapObjSnowRock::initFunc_Break, &TMapObjSnowRock::doFunc_Break, + 1, &TMapObjSnowRock::initFunc_Die, &TMapObjSnowRock::doFunc_Die, + 2, &TMapObjSnowRock::initFunc_Stand, &TMapObjSnowRock::doFunc_Stand +}; + +f32 TMapObjSnowRock::sGravity = 0.01f; +f32 TMapObjSnowRock::sStartVel = 70.0f; +TSnowRockSupervisor *TMapObjSnowRock::sSupervisor; + +void TSnowRockSupervisor::calc() { + for (JSULink *linkA = _24.getFirst(); linkA != nullptr; linkA = linkA->getNext()) { + for (JSULink *linkB = linkA; linkB != nullptr; linkB = linkB->getNext()) { + if (linkA != linkB) { + linkA->getObject()->hitCheck(linkB->getObject()); + } + } + } +} + +TMapObjSnowRock::TMapObjSnowRock(const CrsData::SObject &sObject) : TMapObjHioNode(sObject), JKRDisposer(), _170(this) { + setObjFlagSimpleDraw(); + createSoundMgr(); + _180 = new CrsGround(RCMGetCourse()); + if (getSupervisor() == nullptr) { + sSupervisor = new TSnowRockSupervisor(); + } + sSupervisor->_24.append(&_170); +}; + +TMapObjSnowRock::~TMapObjSnowRock() { + delete _180; + sSupervisor = nullptr; +} + +void TMapObjSnowRock::InitExec() { + Observer_FindAndInit(TMapObjSnowRock, 3); +} + +void TMapObjSnowRock::MoveExec() { + Observer_FindAndExec(TMapObjSnowRock, 3); +} + +const char *TMapObjSnowRock::getBmdFileName() { + static const char *cBmdName = "/Objects/SnowRock1.bmd"; + return cBmdName; +} + +void TMapObjSnowRock::createColModel(J3DModelData *modelData) { + f32 scaleXZ = mScale.x > mScale.z + ? mScale.x + : mScale.z; + + f32 max = scaleXZ > mScale.y + ? scaleXZ + : mScale.y; + + createBoundsCylinder(modelData, 500.0f * (scaleXZ / max), + 950.0f * (mScale.y / max) + ); +} + +void TMapObjSnowRock::doKartColCallBack(int kartIdx) { + JGeometry::TVec3f kartPos; + JGeometry::TVec3f kartVel; + JGeometry::TVec3f colVel; + + mSoundMgr->setSe(0x1005b); + if ((GetKartCtrl()->getKartBody(kartIdx)->mCarStatus & 0x40000) != 0) { + setState(1); + } else { + static const JGeometry::TVec3f axisY(0.0f, 1.0f, 0.0f); + ObjUtility::getKartPos(kartIdx, &kartPos); + setAttacked(kartPos, getBounds(0)->getBoundDepth()); + ObjUtility::getKartVel(kartIdx, &kartVel); + kartVel.normalize(); + kartPos.set(mVel); + if (kartPos.dot(kartVel) > 0.8f) { + colVel.scaleAdd(-kartVel.dot(kartPos), kartVel, kartPos); + if (colVel.isZero()) { + colVel.cross(kartVel, axisY); + colVel.normalize(); + } + colVel.y = 0.0f; + colVel.setLength(30.0f); + mVel.add(colVel); + } + } +} + +void TMapObjSnowRock::setAttacked(const JGeometry::TVec3f &objPos, f32 param_2) { + JGeometry::TVec3f local_28; + + if (RCMGetManager()->getRaceMode() != TIME_ATTACK) { + local_28.sub(mPos, objPos); + local_28.normalize(); + local_28.scale(sStartVel * SiUtil::getNormalRange(param_2, 0.0f, 30.0f)); + mVel.add(local_28); + } +} + +void TMapObjSnowRock::reset() { + resetObject(); + setObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + mReaction.setFlg(8, 0); + mReaction.setFlg(7, 0); + _58 = 19; + _184 = mObjData->mParam1 * 0.001f; + if (_184 == 0.0f) { + _184 = 0.99f; + } + ResetState(); +} + +void TMapObjSnowRock::calc() { + ExecuteState(); +} + +void TMapObjSnowRock::initFunc_Stand() { + mVel.zero(); +} + +void TMapObjSnowRock::doFunc_Stand() { + JGeometry::TVec3f newPos; + newPos.set(mPos); + mVel.scale(_184); + mVel.y = mVel.y - sGravity; + mPos.add(mVel); + _180->search(mPos, newPos); + f32 crsHeight = _180->getHeight(); + if (mPos.y < crsHeight) { + mPos.y = crsHeight; + mVel.y = 0.0f; + } + if (_180->getAttribute() != 4) { + setState(1); + } + checkItemHitting(); + if (!mVel.isZero()) { + mSoundMgr->setSeWithVelocityV(0x40031, SiUtil::getNormalRange(mVel.length(), 0.0f, 30.0f), 0.3f); + } +} + +void TMapObjSnowRock::checkItemHitting() { + if (!tstItemHitting()) { + return; + } + JGeometry::TVec3f pos; + switch (getColItemObj()->getKind()) { + case 7: { + pos = getColItemObj()->getPos(); + f32 depth = getBounds(0)->getBoundDepth(); + setAttacked(pos, depth); + break; + } + case 1: { + pos = getColItemObj()->getPos(); + setAttacked(pos, getColItemObj()->getVel().length()); + break; + } + case 8: + setState(1); + break; + } +} + +void TMapObjSnowRock::initFunc_Break() { + clrAllCheckKartHitFlag(); + clrObjFlagCheckItemHitting(); + makeBreakEmitter(); + mSoundMgr->setSe(0x40030); + _58 = 0; +} + +void TMapObjSnowRock::makeBreakEmitter() { + JPABaseEmitter *baseEmitter; + baseEmitter = JPEffectMgr::getEffectMgr()->createEmt("mk_icerockCrash_a", mPos); + baseEmitter->setGlobalScale(mScale); + baseEmitter = JPEffectMgr::getEffectMgr()->createEmt("mk_icerockCrash_b", mPos); + baseEmitter->setGlobalScale(mScale); + baseEmitter = JPEffectMgr::getEffectMgr()->createEmt("mk_icerockCrash_c", mPos); + baseEmitter->setGlobalScale(mScale); +} + +void TMapObjSnowRock::doFunc_Break() { + setState(2); +} + +void TMapObjSnowRock::initFunc_Die() { + setObjFlagHidding(); +} + +void TMapObjSnowRock::doFunc_Die() {} + +// FIX: Register mismatch. +void TMapObjSnowRock::hitCheck(TMapObjSnowRock *objSnowRock) { + JGeometry::TVec3f rockPos = objSnowRock->mPos; + if (getBounds(0)->IsHitCylinder(mPos, rockPos, *(ObjColCylinder *)objSnowRock->getBounds(0))) { + JGeometry::TVec3f diff; + diff.sub(mPos, rockPos); + diff.normalize(); + diff.scale(sStartVel * SiUtil::getNormalRange(getBounds(0)->getBoundDepth(), 0.0f, 30.0f)); + mVel.add(diff); + } +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 0b1b57ce416471def9b64925207249b586b47070 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 02:50:35 +1000 Subject: [PATCH 18/29] GeoObjMgr - Implement TestRollObj. --- include/Shiraiwa/TestRollObj.h | 32 +++++++++++++++++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/TestRollObj.cpp | 56 ++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/TestRollObj.h diff --git a/include/Shiraiwa/TestRollObj.h b/include/Shiraiwa/TestRollObj.h new file mode 100644 index 00000000..cb37d848 --- /dev/null +++ b/include/Shiraiwa/TestRollObj.h @@ -0,0 +1,32 @@ +#ifndef TESTROLLOBJ_H +#define TESTROLLOBJ_H + +#include "JSystem/J3D/J3DModel.h" +#include "Kaneshige/Course/CrsData.h" +#include "Shiraiwa/Coord3DUtil.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "types.h" + +class TTestRollObj : public TMapObjHioNode { +public: + TTestRollObj(const CrsData::SObject &); // 0x802b0ad4 + virtual ~TTestRollObj(); // 0x802b0b5c + virtual const char *getBmdFileName(); // 0x802b0c10 + virtual void reset(); // 0x802b0c38 + virtual void calc(); // 0x802b0cc4 + virtual void createColModel(J3DModelData *); // 0x802b0cf4 + virtual void doKartColCallBack(int); // 0x802b0d20 + + static f32 sRotSpeed; // 0x804152c0 + + // Inline/Unused + static f32 sAirFriction; + static f32 sGravitySize; + static f32 sReflectRate; + + + u8 test[0x154 - 0x14c]; // 0x14c + TFreeFallShakeSky *mFreeFallShakeSky; // 0x154 + +}; // class TestRollObj +#endif // TESTROLLOBJ_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 10b605a8..d53e1226 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -50,6 +50,7 @@ #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjSnowRock.h" #include "Shiraiwa/Objects/MapObjWanwan.h" +#include "Shiraiwa/TestRollObj.h" #include "Sato/GeographyObjMgr.h" #define GEO_OBJ_NEW(GeoClassName) \ @@ -126,7 +127,7 @@ GEO_OBJ_NEW(TMapObjGeyserSearch); // GEO_OBJ_NEW_S(TTestStrItem); // GEO_OBJ_NEW(TMapObjPeachTree); GEO_OBJ_NEW(TMapObjSnowRock); -// GEO_OBJ_NEW(TTestRollObj); +GEO_OBJ_NEW(TTestRollObj); // GEO_OBJ_NEW(TMapObjFountain); // GEO_OBJ_NEW(TMapObjHeyho); // GEO_OBJ_NEW_S(TMapObjSubHeyho); diff --git a/src/Shiraiwa/TestRollObj.cpp b/src/Shiraiwa/TestRollObj.cpp index e69de29b..09185bba 100644 --- a/src/Shiraiwa/TestRollObj.cpp +++ b/src/Shiraiwa/TestRollObj.cpp @@ -0,0 +1,56 @@ +#include "Shiraiwa/TestRollObj.h" +#include "JSystem/JGeometry/Vec.h" +#include "Sato/ObjUtility.h" +#include "Shiraiwa/Coord3DUtil.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +f32 TTestRollObj::sRotSpeed = 0.95f; + +// Inline/Unused +f32 TTestRollObj::sAirFriction; +f32 TTestRollObj::sGravitySize; +f32 TTestRollObj::sReflectRate; + +TTestRollObj::TTestRollObj(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { + mFreeFallShakeSky = new TFreeFallShakeSky(&mPos, &mVel, &mRotMtx); +} + +TTestRollObj::~TTestRollObj() { + delete mFreeFallShakeSky; +} + +const char *TTestRollObj::getBmdFileName() { + static const char *cBmdName = "/Objects/TestPaipo1.bmd"; + return cBmdName; +} + +void TTestRollObj::reset() { + resetObject(); + _58 = 4; + mFreeFallShakeSky->reset(); + mFreeFallShakeSky->mGravity = 50.0f * mScale.y; + mFreeFallShakeSky->mRotSpeed = sRotSpeed / mScale.y; + mFreeFallShakeSky->mRnd = getGeoRnd(); + mFreeFallShakeSky->mEnabled = true; +} +void TTestRollObj::calc() { + mFreeFallShakeSky->update(); +} + +void TTestRollObj::createColModel(J3DModelData *modelData) { + createBoundsSphere(modelData); +} + +void TTestRollObj::doKartColCallBack(int kartIdx) { + JGeometry::TVec3f kartPos; + JGeometry::TVec3f collisionVec; + + ObjUtility::getKartPos(kartIdx, &kartPos); + collisionVec.sub(mPos, kartPos); + collisionVec.normalize(); + collisionVec.y = 0.5f; + collisionVec.scale(3.0f); + mVel.add(collisionVec); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 5eb6b59dadc58dace2a85c9ae387b793ae098e8e Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 16:29:05 +1000 Subject: [PATCH 19/29] GeoObjMgr - Implement majority of TestString. There are a few things left to do with this class; specifically I gave up trying to get `TTestString::drawNode` to match, and there is a register mismatch on `TTestStrBarrel::checkItemHitting()`. --- include/Sato/GeographyObjMgr.h | 7 +- include/Sato/StringObj.h | 17 +- include/Shiraiwa/TestString.h | 129 ++++++++++ include/dolphin/gx/GXVert.h | 2 + src/Sato/GeographyObjMgr.cpp | 12 +- src/Shiraiwa/TestString.cpp | 458 +++++++++++++++++++++++++++++++++ 6 files changed, 620 insertions(+), 5 deletions(-) create mode 100644 include/Shiraiwa/TestString.h diff --git a/include/Sato/GeographyObjMgr.h b/include/Sato/GeographyObjMgr.h index 293fe5fc..cb5504c5 100644 --- a/include/Sato/GeographyObjMgr.h +++ b/include/Sato/GeographyObjMgr.h @@ -68,6 +68,8 @@ class GeographyObjManager : JKRDisposer return &mKartHitRefVec[myNum]; } + void getKartCollidePosRadius(JGeometry::TVec3f &, f32 &, int); + static GeographyObjManager *gMgr; u8 _18[0x10]; // 18 @@ -78,7 +80,10 @@ class GeographyObjManager : JKRDisposer bool mKartHitItemBox[8]; // 348 u8 _350[0xAC]; // 350 TJugem *mJugem[4]; // 3FC - u8 _40C[0x491 - 0x40C]; // 40C + u8 _40C[0x410 - 0x40C]; // 40C + JGeometry::TVec3f mKartCollidePos[8]; // 410 + f32 mKartCollideRadius[8]; // 470 + u8 _490; // 490 bool mIsBalloonBattle; // 491 bool mIsBombBattle; // 492 bool mIsRobberyBattle; // 493 diff --git a/include/Sato/StringObj.h b/include/Sato/StringObj.h index d5a6d723..965f7c2e 100644 --- a/include/Sato/StringObj.h +++ b/include/Sato/StringObj.h @@ -100,6 +100,21 @@ class StringNodeManager { _3c = val; } + + void link_set_30(u32 num, bool val) { +#line 112 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + mStrNodeList.getNth(num)->getObject()->_30 = val; + } + + void setNodeLength(u32 num, f32 val) { +#line 202 + JUT_MINMAX_ASSERT(0, num, mStrNodeList.getNumLinks()); + mStrNodeList.getNth(num)->getObject()->_34 = val; + } + + + // VTBL: 0x0 JSUList mStrNodeList; // 0x4 f32 _10; @@ -108,7 +123,7 @@ class StringNodeManager { f32 _1c; f32 _20; // Scaling multiplier of some sort. f32 _24; // Something related to distance calculations...? - Vec _28; + JGeometry::TVec3f _28; StringNode *_34; GameAudio::ObjectSoundMgr *mObjSoundMgr; // 0x38 u32 _3c; diff --git a/include/Shiraiwa/TestString.h b/include/Shiraiwa/TestString.h new file mode 100644 index 00000000..5635bc3a --- /dev/null +++ b/include/Shiraiwa/TestString.h @@ -0,0 +1,129 @@ +#ifndef TESTSTRING_H +#define TESTSTRING_H + +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JKernel/JKRDisposer.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JSupport/JSUList.h" +#include "JSystem/JUtility/JUTTexture.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" +#include "Sato/Objects/GeoItemBox.h" +#include "Sato/StringObj.h" + +// Forward Declaration. +class TTestString; + +class TTestStrBarrel : public GeographyObj { +public: + TTestStrBarrel() : GeographyObj(0xe0d) {} + virtual ~TTestStrBarrel() {} + virtual void reset(); + virtual void calc(); + virtual u32 getSoundID() const { return 0x10063; }; + virtual const char *getBmdFileName() { return "/Objects/TestHimo1Ukiwa.bmd"; } + virtual const char *getShadowBmdFileName() { return "/Objects/TestHimo1Shadow.bmd"; } + virtual void createColModel(J3DModelData *); + virtual void doKartColCallBack(int); + void moveShadowModel(); + void checkItemHitting(); + void vibrate(int); + + + static f32 sItemVelScale; + static f32 sKartVelScale; + + TTestString *mString; +}; + + +class TTestStrItem : public GeographyObj { +public: + TTestStrItem() : GeographyObj(0xe0b) {} + virtual ~TTestStrItem() {} + virtual void reset(); + virtual void calc(); + virtual void doKartColCallBack(int); + virtual void createColModel(J3DModelData *); + virtual const char *getBmdFileName() { return GeoItemBox::getBmdName(); } + virtual const char *getShadowBmdFileName() { return GeoItemBox::getShadowBmdName(); } + + TTestString *_14c; // 0x14c + u16 _150; // 0x150 (+ 2 bytes padding) + JPABaseEmitter *_154[2]; // 0x154 +}; + + +class TTestStrSupervisor : public GeoObjSupervisor { +public: + TTestStrSupervisor() : GeoObjSupervisor() { + _24.initiate(); + _30 = new JUTTexture(); + }; + virtual ~TTestStrSupervisor(); + virtual void reset() {} + virtual void calc() {} + void drawAll(u32); + virtual void load(); + virtual void createModel(JKRSolidHeap *, u32); + void entry(TTestString *); + + static JGeometry::TVec3f sStringOffset[6]; + static JGeometry::TVec3f sStringTexOffset[4]; + + JSUList _24; + JUTTexture *_30; +}; + +class TTestString : public GeographyObj, public JKRDisposer { +public: + TTestString(const CrsData::SObject &sObject); // 0x802abf28 + virtual ~TTestString(); // 0x802ac110 + virtual void createModel(JKRSolidHeap *, u32); // 0x802ad458 + virtual void reset(); // 0x802ac1e4 + virtual void calc(); // 0x802ac4f4 + virtual TTestStrSupervisor *getSupervisor() { return sSupervisor; } // 0x802ad45c + void load(J3DModelData *); // 0x802ac4f0 + void attack(const JGeometry::TVec3f &); // 0x802ac5b4 + void attack(const JGeometry::TVec3f &, const JGeometry::TVec3f &); // 0x802ac5f4 + void draw(u32); // 0x802ac66c + void drawNode(f32, JGeometry::TVec3f &, JGeometry::TVec3f &, u32); // 0x802ac764 + void drawCrevicePyramid(JGeometry::TVec3f &, JGeometry::TVec3f &, JGeometry::TVec3f &); // 0x802ace90 + void drawPrism(JGeometry::TVec3f &, JGeometry::TVec3f &, JGeometry::TVec3f &, JGeometry::TVec3f &, JGeometry::TVec3f &); // 0x802ad034 + void getUpDir(JGeometry::TVec3f *); // 0x802ad2c4 + void getPoint(JGeometry::TVec3f *); // 0x802ad2e8 + void getPointDir(JGeometry::TVec3f *); // 0x802ad318 + void setParameters(); // 0x802ad430 + + static f32 sAdjustRatio; // 0x80415278 + static f32 sAirFric; // 0x8041527c + static f32 sGravity; // 0x80415280 + static f32 sWidth; // 0x80415284 + static f32 sDownVel; // 0x80415288 + static TTestStrSupervisor *sSupervisor; // 0x80416f18 + + // Inline/Unused + //void JSUList::~JSUList(); + //void JSULink::~JSULink(); + //void TTestStringObj::calc(); + //void TTestStringObj::~TTestStringObj(); + //void TTestStrBarrel::scBombAttackSpeed; + //void TTestStrBarrel::scCenterOffsetY; + //void TTestStrBarrel::scVibrationLimit; + //void TTestStrBarrel::scObjRadius; + + JSULink _164; // 0x164 + ExStringNodeManager *mExStrNodeMgr; // 0x174 + u8 _178[0x17c - 0x178]; // 0x178 - Unused? + TTestStrItem *_17c; // 0x17c + u8 _180; // 0x180 + u8 _181[3]; // 0x181 + f32 _184; // 0x184 + f32 *_188; // 0x188 + JGeometry::TVec3f _18c[3]; // 0x18c + +}; // class TestString + +#endif // TESTSTRING_H diff --git a/include/dolphin/gx/GXVert.h b/include/dolphin/gx/GXVert.h index 7bce7e4a..6b28ca63 100644 --- a/include/dolphin/gx/GXVert.h +++ b/include/dolphin/gx/GXVert.h @@ -62,6 +62,8 @@ static inline void GXNormal3f32(const f32 x, const f32 y, const f32 z) GXWGFifo.f32 = z; } +static inline void GXColor1u8(const u8 c) { GXWGFifo.u8 = c; } + static inline void GXColor1u32(const u32 c) { GXWGFifo.u32 = c; } static inline void GXColor4u8(const u8 r, const u8 g, const u8 b, const u8 a) diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index d53e1226..67839cb0 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -51,6 +51,7 @@ #include "Shiraiwa/Objects/MapObjSnowRock.h" #include "Shiraiwa/Objects/MapObjWanwan.h" #include "Shiraiwa/TestRollObj.h" +#include "Shiraiwa/TestString.h" #include "Sato/GeographyObjMgr.h" #define GEO_OBJ_NEW(GeoClassName) \ @@ -123,8 +124,8 @@ GEO_OBJ_NEW(GeoVision); // GEO_OBJ_NEW_S(TSMAKamome); GEO_OBJ_NEW(TMapObjGeyser); GEO_OBJ_NEW(TMapObjGeyserSearch); -// GEO_OBJ_NEW_S(TTestStrBarrel); -// GEO_OBJ_NEW_S(TTestStrItem); +GEO_OBJ_NEW_S(TTestStrBarrel); +GEO_OBJ_NEW_S(TTestStrItem); // GEO_OBJ_NEW(TMapObjPeachTree); GEO_OBJ_NEW(TMapObjSnowRock); GEO_OBJ_NEW(TTestRollObj); @@ -203,7 +204,7 @@ GEO_OBJ_NEW(GeoItemGen); // GEO_OBJ_NEW(TSMAButterflyGen); // GEO_OBJ_NEW(TSMADonkyBirdGen); // GEO_OBJ_NEW(TSMABoidBirdManager); -// GEO_OBJ_NEW(TTestString); +GEO_OBJ_NEW(TTestString); GEO_OBJ_NEW_S(TBalloonString); GEO_OBJ_NEW(TLensFlare); // GEO_OBJ_NEW(TDistSnow); @@ -226,3 +227,8 @@ EX_GEO_OBJ_NEW(GeoJumpNarrow); #pragma endregion // GeoObj Definitions + +void GeographyObjManager::getKartCollidePosRadius(JGeometry::TVec3f &kartCollidePos, f32 &kartCollideRadius, int p3) { + kartCollidePos = mKartCollidePos[p3]; + kartCollideRadius = mKartCollideRadius[p3]; +} diff --git a/src/Shiraiwa/TestString.cpp b/src/Shiraiwa/TestString.cpp index e69de29b..342f0f5e 100644 --- a/src/Shiraiwa/TestString.cpp +++ b/src/Shiraiwa/TestString.cpp @@ -0,0 +1,458 @@ +#include "Shiraiwa/TestString.h" +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/J3D/J3DModelLoader.h" +#include "JSystem/J3D/J3DTransform.h" +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/ResTIMG.h" +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/Objects/GeoItemCar.h" +#include "Kaneshige/RaceMgr.h" +#include "Sato/GeographyObj.h" +#include "Sato/GeographyObjMgr.h" +#include "Sato/ObjUtility.h" +#include "Sato/StringObj.h" +#include "Yamamoto/kartCtrl.h" +#include "dolphin/gx/GXEnum.h" +#include "dolphin/gx/GXGeometry.h" +#include "dolphin/gx/GXLighting.h" +#include "dolphin/gx/GXStruct.h" +#include "dolphin/gx/GXTransform.h" +#include "dolphin/gx/GXVert.h" +#include "dolphin/mtx.h" +#include "types.h" + +f32 TTestStrBarrel::sItemVelScale = 0.6f; +f32 TTestStrBarrel::sKartVelScale = 3.0f; + +f32 TTestString::sAdjustRatio = 0.2f; +f32 TTestString::sAirFric = 0.999999f; +f32 TTestString::sGravity = -0.2f; +f32 TTestString::sWidth = 20.0f; +f32 TTestString::sDownVel = 5.0f; + +TTestStrSupervisor *TTestString::sSupervisor; + +void TTestStrBarrel::reset() { + GeographyObj::resetObject(); + setObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + clrObjFlagHidding(); + _58 = 0; +} + +void TTestStrBarrel::calc() { + JGeometry::TVec3f local_70; + JGeometry::TVec3f pointDir; + JGeometry::TVec3f zNorm; + mString->getPoint(&mPos); + zNorm.set(mString->mObjData->zNorm); + mString->getPointDir(&pointDir); + pointDir.negate(); + local_70.cross(pointDir, zNorm); + local_70.normalize(); + zNorm.cross(local_70, pointDir); + zNorm.normalize(); + mPos.scaleAdd(-100.0f, pointDir, mPos); + mRotMtx.setXYZDir(local_70, pointDir, zNorm); + checkItemHitting(); + moveShadowModel(); +} + +void TTestStrBarrel::moveShadowModel() { + JGeometry::TPos3f newRotMtx; + + if (!mShadowMdl->isInvisibleAll()) { + CrsGround crsGround = RaceMgr::sRaceManager->getCourse(); + crsGround.search(this, mPos, mPos); + + PSMTXCopy(mRotMtx, newRotMtx.mMtx); + newRotMtx[0][3] = mPos.x; + newRotMtx[1][3] = crsGround.getHeight(); + newRotMtx[2][3] = mPos.z; + mShadowMdl->setBaseTRMtx(newRotMtx); + + J3DModel *model = getShadowModel()->getModel(); + model->setBaseScale(mScale); + } +} + +// FIX: Register mismatch. +void TTestStrBarrel::checkItemHitting() { + JGeometry::TVec3f vel; + JGeometry::TVec3f diff; + JGeometry::TVec3f itemPos; + if (tstItemHitting()) { + u32 itemKind = mColItemObj->getKind(); + + switch (itemKind) { + case 0: + case 1: + case 2: + case 7: + case 9: + case 11: { + vel.set(mColItemObj->mVel); + if (mReaction.tstFlg(itemKind) == 1) { + vel.negate(); + } + vel.scale(sItemVelScale); + mString->attack(vel); + break; + + } + case 8: + { + // FIX: Register mismatches here: + itemPos = mColItemObj->mPos; + diff.sub(mPos, itemPos); + diff.setLength(50.0f); + mString->attack(diff); + break; + } + + case 3: + case 4: + case 5: + case 6: + case 10: + default: + break; + } + } +} + +void TTestStrBarrel::createColModel(J3DModelData *modelData) { + GeographyObj::createBoundsSphere(115.0f, 1.0f); +} + +void TTestStrBarrel::doKartColCallBack(int kartIdx) { + JGeometry::TVec3f kartVel; + ObjUtility::getKartVel(kartIdx, &kartVel); + + if (kartVel.squared() < 1.0f) { + kartVel.zero(); + } + + kartVel.scale(sKartVelScale); + + JGeometry::TVec3f kartPos; + f32 radius; + GetGeoObjMgr()->getKartCollidePosRadius(kartPos, radius, kartIdx); + + JGeometry::TVec3f dir; + dir.sub(getBoundsGlPos(0), kartPos); + dir.normalize(); + + JGeometry::TVec3f forward; + mRotMtx.getYDir(forward); + forward.normalize(); + forward.scale(100.0f); + + JGeometry::TVec3f attackPos; + attackPos.scaleAdd(radius + 115.0f, dir, kartPos); + attackPos.add(forward); + + mString->attack(attackPos, kartVel); + + vibrate(kartIdx); + GetKartCtrl()->getKartSound(kartIdx)->mSoundMgr->setCrushSe(getSoundID(), mBounds[0]->getBoundDepth() * 0.03f); +} + +void TTestStrBarrel::vibrate(int kartIdx) { + JGeometry::TVec3f kartVel; + ObjUtility::getKartVel(kartIdx, &kartVel); + if (kartVel.squared() > 100.0f) { + GetKartCtrl()->getKartBody(kartIdx)->getStrat()->DoMotor((MotorManager::MotorType)getMotorType()); + } +} + + +void TTestStrItem::reset() { + GeographyObj::resetObject(); + clrObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + clrObjFlagHidding(); + _150 = 0; + _58 = 0; + for (int i = 0; i < 2; i++) { + _154[i] = nullptr; + } +} + +void TTestStrItem::calc() { + JGeometry::TVec3f xDir; + JGeometry::TVec3f yDir; + JGeometry::TVec3f zDir; + + _14c->getPoint(&mPos); + zDir.set(0.0f, 0.0f, 1.0f); + _14c->getPointDir(&yDir); + + xDir.cross(yDir, zDir); + xDir.normalize(); + zDir.cross(xDir, yDir); + zDir.normalize(); + mRotMtx.setXYZDir(xDir, yDir, zDir); + + GeographyObj::moveShadowModel(); + if (tstObjFlagHidding()) { + _150++; + if (_150 > 600) { + setAllCheckKartHitFlag(); + clrObjFlagHidding(); + _150 = 0; + } + } +} + +void TTestStrItem::doKartColCallBack(int kartIdx) { + if (tstIsHitKartFlg(kartIdx) != 0) { + GeoItemCar::hitItemBoxProc(kartIdx, _154); + clrAllCheckKartHitFlag(); + setObjFlagHidding(); + } +} + +void TTestStrItem::createColModel(J3DModelData *modelData) { + GeographyObj::createBoundsSphere(150.0f, 1.0f); +} + +TTestStrSupervisor::~TTestStrSupervisor() { + delete _30; +} + +void TTestStrSupervisor::drawAll(u32 param_1) { + GXColor white = {0xff, 0xff, 0xff, 0xff}; + GXSetTevColor(GX_TEVREG0, white); + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GXSetNumTexGens(1); + GXSetNumTevStages(1); + GXSetNumChans(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x1e, GX_FALSE, 0x7d); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE); + GXSetCurrentMtx(0); + GXSetCullMode(GX_CULL_NONE); + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_F32, 0); + GXSetAlphaUpdate(GX_TRUE); + GXSetAlphaCompare(GX_GREATER, GX_FALSE, GX_AOP_OR, GX_GREATER, GX_FALSE); + _30->load(GX_TEXMAP0); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0); + GXSetArray(GX_VA_TEX0, &sStringTexOffset, 8); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_F32, 0); + for (JSULink *testStr = _24.getFirst(); testStr != nullptr; testStr = testStr->getNext()) { + testStr->getObject()->draw(param_1); + } +} + +void TTestStrSupervisor::load() { + ResTIMG *timg = (ResTIMG *)ObjUtility::getPtrCourseArc("/Objects/TestHimo1Tex.bti"); + JUT_ASSERT(timg != 0); + timg->mWrapS = 1; + _30->storeTIMG(timg); + + J3DModelData *modelData = J3DModelLoaderDataBase::load(ObjUtility::getPtrCourseArc("/Objects/TestHimo1.bmd"), 0x19200010); + modelData->newSharedDisplayList(0x40000); + modelData->simpleCalcMaterial(0, j3dDefaultMtx); + modelData->makeSharedDL(); + + for (JSULink *testStr = _24.getFirst(); testStr != nullptr; testStr = testStr->getNext()) { + testStr->getObject()->load(modelData); + } +} + +void TTestStrSupervisor::createModel(JKRSolidHeap *jkrSolidHeap, u32 p2) { + for (JSULink *testStr = _24.getFirst(); testStr != nullptr; testStr = testStr->getNext()) { + testStr->getObject()->createModel(jkrSolidHeap, p2); + } +} + +TTestString::TTestString(const CrsData::SObject &sObject) : GeographyObj(sObject), JKRDisposer(), _164(this) { + _180 = sObject.mParam1; + if (_180 < 2) { + _180 = 5; + } + + _184 = sObject.mParam2; + if (_184 <= 0.0f) { + _184 = 1000.0f; + } + + _188 = new f32[_180]; + + mExStrNodeMgr = new ExStringNodeManager(_180, 30.0f, true, false, 0); + + if (sSupervisor == nullptr) { + sSupervisor = new TTestStrSupervisor(); + } + sSupervisor->_24.append(&_164); + + _17c = (TTestStrItem *)GetGeoObjMgr()->createSubObj(0xE0D); + _17c->_14c = this; +} + +TTestString::~TTestString() { + sSupervisor = nullptr; + delete mExStrNodeMgr; +} + +void TTestString::reset() { + GeographyObj::resetObject(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + PSMTXIdentity(mRotMtx); + mExStrNodeMgr->resetNodeAll(nullptr); + + if (mObjData->mParam3 == 0) { + f32 dVar5 = _184; + for (u32 i = 0; i < _180 - 1; i++) { + dVar5 *= 0.5f; + _188[i] = dVar5; + + mExStrNodeMgr->setNodeLength(i, _188[i]); + mExStrNodeMgr->link_set_30(i, false); + } + _188[_180 - 1] = dVar5; + mExStrNodeMgr->setNodeLength(_180 - 1, _188[_180 - 1]); + + } else { + f32 nodeLen = _184 / _180; + mExStrNodeMgr->setNodeLengthAll(nodeLen); + for (u32 i = 0; i < _180 - 1; i++) { + _188[i] = nodeLen; + mExStrNodeMgr->link_set_30(i, false); + } + } + setParameters(); +} + +void TTestString::load(J3DModelData *modelData) {} + +void TTestString::calc() { + JGeometry::TVec3f upDir; + JGeometry::TVec3f nodeVel; + + getUpDir(&upDir); + mExStrNodeMgr->_28 = upDir; + mExStrNodeMgr->calc(); + mExStrNodeMgr->setNodePos(0, mObjData->position); + nodeVel.scale(-sDownVel, upDir); + mExStrNodeMgr->addNodeVel(_180 - 1, nodeVel); +} + +void TTestString::attack(const JGeometry::TVec3f ¶m_1) { + mExStrNodeMgr->addNodeVel(_180 - 1, param_1); +} + +void TTestString::attack(const JGeometry::TVec3f ¶m_1, const JGeometry::TVec3f ¶m_2) { + mExStrNodeMgr->setNodePos(_180 - 1, param_1); + mExStrNodeMgr->addNodeVel(_180 - 1, param_2); +} + +void TTestString::draw(u32 param_1) { + JGeometry::TVec3f nodePosOne; + JGeometry::TVec3f nodePosTwo; + + for (int i = 0; i < _180 - 1; i++) { + mExStrNodeMgr->getNodePos(i, &nodePosOne); + mExStrNodeMgr->getNodePos(i + 1, &nodePosTwo); + if (i == 0) { + _18c[0].set(nodePosOne); + _18c[1].set(nodePosOne.x + sWidth, nodePosOne.y, nodePosOne.z); + _18c[2].set(sWidth * 0.5f + nodePosOne.x, nodePosOne.y, sWidth * 0.85f + nodePosOne.z); + } + drawNode(_188[i], nodePosOne, nodePosTwo, param_1); + } +} + +void TTestString::drawNode(f32 param_1, JGeometry::TVec3f ¶m_2, JGeometry::TVec3f ¶m_3, u32 cameraNo) { + +} + +void TTestString::drawCrevicePyramid(JGeometry::TVec3f &p1, JGeometry::TVec3f &p2, JGeometry::TVec3f &p3) { + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 5); + GXPosition3f32(_18c[0].x, _18c[0].y, _18c[0].z); + GXColor1u8(3); + GXPosition3f32(_18c[1].x, _18c[1].y, _18c[1].z); + GXColor1u8(0); + GXPosition3f32(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z); + GXColor1u8(4); + GXPosition3f32(p1.x + p3.x, p1.y + p3.y, p1.z + p3.z); + GXColor1u8(1); + GXPosition3f32(_18c[2].x, _18c[2].y, _18c[2].z); + GXColor1u8(2); + GXEnd(); + GXBegin(GX_TRIANGLES, GX_VTXFMT0, 3); + GXPosition3f32(_18c[0].x, _18c[0].y, _18c[0].z); + GXColor1u8(3); + GXPosition3f32(p1.x + p3.x, p1.y + p3.y, p1.z + p3.z); + GXColor1u8(0); + GXPosition3f32(_18c[2].x, _18c[2].y, _18c[2].z); + GXColor1u8(4); + GXEnd(); +} + +void TTestString::drawPrism(JGeometry::TVec3f &p1, JGeometry::TVec3f &p2, JGeometry::TVec3f &p3, JGeometry::TVec3f &p4, JGeometry::TVec3f &p5) { + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 5); + GXPosition3f32(p2.x + p3.x, p2.y + p3.y, p2.z + p3.z); + GXColor1u8(3); + GXPosition3f32(p1.x + p3.x, p1.y + p3.y, p1.z + p3.z); + GXColor1u8(0); + GXPosition3f32(p2.x + p4.x, p2.y + p4.y, p2.z + p4.z); + GXColor1u8(4); + GXPosition3f32(p1.x + p4.x, p1.y + p4.y, p1.z + p4.z); + GXColor1u8(1); + GXPosition3f32(p1.x + p5.x, p1.y + p5.y, p1.z + p5.z); + GXColor1u8(2); + GXEnd(); + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 5); + GXPosition3f32(p2.x + p4.x, p2.y + p4.y, p2.z + p4.z); + GXColor1u8(4); + GXPosition3f32(p1.x + p5.x, p1.y + p5.y, p1.z + p5.z); + GXColor1u8(2); + GXPosition3f32(p2.x + p5.x, p2.y + p5.y, p2.z + p5.z); + GXColor1u8(5); + GXPosition3f32(p1.x + p3.x, p1.y + p3.y, p1.z + p3.z); + GXColor1u8(0); + GXPosition3f32(p2.x + p3.x, p2.y + p3.y, p2.z + p3.z); + GXColor1u8(3); + GXEnd(); +} + +void TTestString::getUpDir(JGeometry::TVec3f *upDir) { + JGeometry::TVec3f *yDir = RCMGetCourse()->getDirY(); + f32 upDirX = yDir->x; + f32 upDirY = yDir->y; + f32 upDirZ = yDir->z; + upDir->set(upDirX, upDirY, upDirZ); +} + +void TTestString::getPoint(JGeometry::TVec3f *point) { + mExStrNodeMgr->getNodePos(_180 - 1, point); +} + +void TTestString::getPointDir(JGeometry::TVec3f *dir) { + JGeometry::TVec3f nodeTwoPos; + JGeometry::TVec3f nodeOnePos; + mExStrNodeMgr->getNodePos(_180 - 2, &nodeTwoPos); + mExStrNodeMgr->getNodePos(_180 - 1, &nodeOnePos); + dir->sub(nodeOnePos, nodeTwoPos); + dir->normalize(); +} + +void TTestString::setParameters() { + mExStrNodeMgr->_24 = sAdjustRatio; + mExStrNodeMgr->_20 = sAirFric; + mExStrNodeMgr->_1c = sGravity; +} + +void TTestString::createModel(JKRSolidHeap *, u32) {} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 09a92669073015c295fe2ac223789acc62ee8553 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 16:51:42 +1000 Subject: [PATCH 20/29] GeoObjMgr - Implement TMapObjFountain. --- include/Shiraiwa/Objects/MapObjFountain.h | 40 ++++++++++ src/Sato/GeographyObjMgr.cpp | 5 +- src/Shiraiwa/MapObjFountain.cpp | 93 +++++++++++++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 include/Shiraiwa/Objects/MapObjFountain.h diff --git a/include/Shiraiwa/Objects/MapObjFountain.h b/include/Shiraiwa/Objects/MapObjFountain.h new file mode 100644 index 00000000..ceb7f91a --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjFountain.h @@ -0,0 +1,40 @@ +#ifndef MAPOBJFOUNTAIN_H +#define MAPOBJFOUNTAIN_H + +#include "JSystem/J3D/J3DAnmTextureSRTKey.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/J3DAnmObject.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjFountain : public TMapObjHioNode { +public: + TMapObjFountain(const CrsData::SObject &); // 0x802b0f6c + ~TMapObjFountain(); // 0x802b100c + virtual const char *getBmdFileName(); // 0x802b10dc + virtual void reset(); // 0x802b1104 + virtual void createModel(JKRSolidHeap *, u32); // 0x802b1180 + virtual void loadAnimation(); // 0x802b11bc + virtual void calc(); // 0x802b1204 + virtual void update(); // 0x802b1250 + + static J3DAnmTextureSRTKey *sFountainBtkAnm; // 0x80416f58 + + J3DAnmObjMaterial mAnmObj; +}; // class MapObjFountain + +class TMapObjDemoFountain : public TMapObjFountain { +public: + TMapObjDemoFountain(const CrsData::SObject &); + virtual ~TMapObjDemoFountain(); + virtual void createModel(JKRSolidHeap *, u32); + virtual void loadAnimation(); + virtual void reset(); + virtual void calc(); + virtual const char *getBmdFileName() { return "/Objects/DPeachFountain.bmd"; } + + static J3DAnmTextureSRTKey *sDemoFountainBtkAnm; + bool mIsMakeEmt; +}; + +#endif // MAPOBJFOUNTAIN_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 67839cb0..1c6992ae 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -45,6 +45,7 @@ #include "Shiraiwa/Objects/MapObjDonkyRockGen.h" #include "Shiraiwa/Objects/MapObjDonkyTree.h" #include "Shiraiwa/Objects/MapObjDossun.h" +#include "Shiraiwa/Objects/MapObjFountain.h" #include "Shiraiwa/Objects/MapObjGeyser.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" @@ -129,7 +130,7 @@ GEO_OBJ_NEW_S(TTestStrItem); // GEO_OBJ_NEW(TMapObjPeachTree); GEO_OBJ_NEW(TMapObjSnowRock); GEO_OBJ_NEW(TTestRollObj); -// GEO_OBJ_NEW(TMapObjFountain); +GEO_OBJ_NEW(TMapObjFountain); // GEO_OBJ_NEW(TMapObjHeyho); // GEO_OBJ_NEW_S(TMapObjSubHeyho); // GEO_OBJ_NEW(TMapObjSanbo); @@ -181,7 +182,7 @@ GEO_OBJ_NEW(TMapObjAntLion); // GEO_OBJ_NEW(TMapObjPakkun); GEO_OBJ_NEW(GeoKinojii); GEO_OBJ_NEW(TMapObjDinoTree); -// GEO_OBJ_NEW(TMapObjDemoFountain); +GEO_OBJ_NEW(TMapObjDemoFountain); // GEO_OBJ_NEW(TMapObjKpGear); // GEO_OBJ_NEW(TMapObjKpFireBar); // GEO_OBJ_NEW(TMapObjSwimNossie); diff --git a/src/Shiraiwa/MapObjFountain.cpp b/src/Shiraiwa/MapObjFountain.cpp index e69de29b..384e262a 100644 --- a/src/Shiraiwa/MapObjFountain.cpp +++ b/src/Shiraiwa/MapObjFountain.cpp @@ -0,0 +1,93 @@ +#include "JSystem/J3D/J3DAnmTextureSRTKey.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/JPEffectMgr.h" +#include "Sato/ObjUtility.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "Shiraiwa/Objects/MapObjFountain.h" + +J3DAnmTextureSRTKey *TMapObjFountain::sFountainBtkAnm; + +TMapObjFountain::TMapObjFountain(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { + setObjFlagSimpleDraw(); + createSoundMgr(); +} + +TMapObjFountain::~TMapObjFountain() {} + +const char *TMapObjFountain::getBmdFileName() { + static const char *cBmdName = "/Objects/PeachFountain.bmd"; + return cBmdName; +} + +void TMapObjFountain::reset() { + GeographyObj::resetObject(); + clrObjFlagHidding(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + mAnmObj.resetFrame(); +} + +void TMapObjFountain::createModel(JKRSolidHeap *jkrSolidHeap, u32 p2) { + mAnmObj.mModel = &mModel; + mAnmObj.mAnmBase = sFountainBtkAnm; + mAnmObj.initFrameCtrl(mAnmObj.getAnmBase()); +} + +void TMapObjFountain::loadAnimation() { + J3DModelData *modelData = *mModel.mModelData; + void *ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/PeachFountain.btk"); + J3DAnmObjMaterial::setupTexSRTAnmData(&sFountainBtkAnm, modelData, ptrCourseArc); +} + +void TMapObjFountain::calc() { + mAnmObj.getFrameCtrl()->update(); + getSoundMgr()->setSe(0x40048); +} + +void TMapObjFountain::update() { + mAnmObj.anmFrameProc(); + GeographyObj::update(); +} + + + +J3DAnmTextureSRTKey *TMapObjDemoFountain::sDemoFountainBtkAnm; + +TMapObjDemoFountain::TMapObjDemoFountain(const CrsData::SObject &sObject) : TMapObjFountain(sObject) { + setObjFlagSimpleDraw(); +} + +TMapObjDemoFountain::~TMapObjDemoFountain() {} + +void TMapObjDemoFountain::createModel(JKRSolidHeap *jkrSolidHeap, u32 p2) { + mAnmObj.setExModel(&mModel); + mAnmObj.setAnmBase(sDemoFountainBtkAnm); + mAnmObj.initFrameCtrl(mAnmObj.getAnmBase()); +} + +void TMapObjDemoFountain::loadAnimation() { + J3DModelData *modelData = *mModel.mModelData; + void *ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/DPeachFountain.btk"); + J3DAnmObjMaterial::setupTexSRTAnmData(&sDemoFountainBtkAnm, modelData, ptrCourseArc); +} + +void TMapObjDemoFountain::reset() { + GeographyObj::resetObject(); + clrObjFlagHidding(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + mAnmObj.resetFrame(); + mIsMakeEmt = true; +} + +void TMapObjDemoFountain::calc() { + if (mIsMakeEmt != 0) { + JPEffectMgr::getEffectMgr()->createEmt("mk_fountainWtr_a", mPos); + mIsMakeEmt = 0; + } + mAnmObj.getFrameCtrl()->update(); + getSoundMgr()->setSe(0x40082); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 5147860417121a0759971db3ff699fd204521bec Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 17:16:25 +1000 Subject: [PATCH 21/29] GeoObjMgr - Implement majority of TMapObjHeyho. Note the two register mismatches in `TMapObjHeyho::hitCheck()` and `TMapObjSubHeyho::doFunc_Recover()`. The `hitCheck` mismatch looks similar to what I've seen in a few other functions, and I'm guessing it's just down to how the TVec3f methods or overloads are being called; I just can't work out the combination to use. The `doFunc_Recover` function looks like it uses a slerp/nlerp function; but I couldn't work this one out either - maybe something is missing from the JSystem's TQuat4f implementation? --- include/Shiraiwa/Objects/MapObjHeyho.h | 160 +++++ src/Sato/GeographyObjMgr.cpp | 5 +- src/Shiraiwa/MapObjHeyho.cpp | 770 +++++++++++++++++++++++++ 3 files changed, 933 insertions(+), 2 deletions(-) create mode 100644 include/Shiraiwa/Objects/MapObjHeyho.h diff --git a/include/Shiraiwa/Objects/MapObjHeyho.h b/include/Shiraiwa/Objects/MapObjHeyho.h new file mode 100644 index 00000000..77436966 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjHeyho.h @@ -0,0 +1,160 @@ +#ifndef MAPOBJHEYHO_H +#define MAPOBJHEYHO_H + +#include "JSystem/J3D/J3DAnmTextureSRTKey.h" +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JKernel/JKRDisposer.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" +#include "Sato/J3DAnmObject.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/AnmPlayer.h" +#include "Shiraiwa/Coord3DUtil.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + + +class TMapObjHeyho; + +class THeyhoSupervisor : public GeoObjSupervisor { +public: + THeyhoSupervisor() : GeoObjSupervisor() { + _24.initiate(); + } + virtual ~THeyhoSupervisor() {} + virtual void calc(); + virtual void reset() {}; + + // void THeyhoSupervisor::entry(TMapObjHeyho *); + + JSUList _24; +}; + + +class TMapObjSubHeyho : public GeographyObj, public StateObserver { + public: + TMapObjSubHeyho(); + virtual ~TMapObjSubHeyho() {}; // 0x802b3d98 + virtual void loadAnimation(); + virtual void createModel(JKRSolidHeap *, u32); + virtual void reset(); + virtual void calc(); + virtual void update(); + virtual const char *getBmdFileName(); + virtual const char *getShadowBmdFileName(); + virtual void createColModel(J3DModelData *); + virtual void MoveExec(); // 0x802b33dc + virtual void InitExec(); // 0x802b3370 + bool checkItemHitting(); + void initFunc_Skate(); + void doFunc_Skate(); + void makeFrontMtx(JGeometry::TPos3f *); + void initFunc_Spin(); + void doFunc_Spin(); + void initFunc_Recover(); + void doFunc_Recover(); + + static StateFuncSet sTable[3]; + static TAnmInfo sAnmInfos[1]; + static J3DAnmTexPattern *sHeyhoBtpAnm; + // void TMapObjSubHeyho::scRecoverSpeed; + + J3DAnmObjMaterial mAnmObj; // 0x158 + JGeometry::TVec3f *mSubHeyhoPos; // 0x178 + JGeometry::TVec3f *mSubHeyhoVel; // 0x17c + int _180; // 0x180 - Unknown + JGeometry::TPos3f *mSubHeyhoRot; // 0x184 + JGeometry::TVec3f _188; // 0x188 - scale? + JGeometry::TPos3f _194; // 0x194 + f32 _1c4; // 0x1c4 +}; + + + +class TMapObjHeyho : public TMapObjHioNode, public StateObserver, JKRDisposer { +public: + TMapObjHeyho(const CrsData::SObject &); // 0x802b1718 + virtual ~TMapObjHeyho(); // 0x802b1930 + virtual void MoveExec(); // 0x802b2118 + virtual void InitExec(); // 0x802b20ac + virtual void reset(); // 0x802b1a70 + virtual void calc(); // 0x802b1c4c + void callWalkSound(); // 0x802b1ccc + bool checkItemHitting(); // 0x802b1dcc + void checkJump(u16); // 0x802b1ec0 + virtual const char *getBmdFileName(); // 0x802b1f1c + virtual const char *getShadowBmdFileName(); // 0x802b1f44 + virtual void loadAnimation(); // 0x802b1f6c + virtual void createModel(JKRSolidHeap *, u32); // 0x802b1fcc + virtual void createColModel(J3DModelData *); // 0x802b2044 + virtual void update(); // 0x802b2184 + void changeAllState(u16); // 0x802b21ec + virtual void doKartColCallBack(int); // 0x802b22b0 + void initFunc_Skate(); // 0x802b2360 + void doFunc_Skate(); // 0x802b238c + void initFunc_Jump(); // 0x802b23d8 + void doFunc_Jump(); // 0x802b2504 + void initFunc_Bomb(); // 0x802b264c + void doFunc_Bomb(); // 0x802b289c + void initFunc_BombEnd(); // 0x802b2ad4 + void doFunc_BombEnd(); // 0x802b2ae0 + void initFunc_Sink(); // 0x802b2d38 + void doFunc_Sink(); // 0x802b2d78 + void initFunc_Recover(); // 0x802b2ea8 + void doFunc_Recover(); // 0x802b2ed4 + void initFunc_Die(); // 0x802b2fd0 + void doFunc_Die(); // 0x802b301c + void hitCheck(TMapObjHeyho *); // 0x802b3020 + + static TAnmInfo sAnmInfos[1]; // 0x803a6d78 + static StateFuncSet sTable[7]; // 0x803a6e34 + static f32 sGravity; // 0x804152c8 + static f32 sAccel; // 0x804152cc + static f32 sJumpVel; // 0x804152d0 + static f32 sJumpGrv; // 0x804152d4 + static f32 sRotSpeed; // 0x804152d8 + static f32 sFirstSinkVel; // 0x804152dc + static f32 sSinkAccel; // 0x804152e0 + static f32 sBombVelH; // 0x804152e4 + static f32 sBombVelV; // 0x804152e8 + static f32 sSlideVelH; // 0x804152ec + static f32 sSlideVelV; // 0x804152f0 + static f32 sBombRotSpeed; // 0x804152f4 + static f32 sBombEndRotDecel; // 0x804152f8 + static f32 sAirFriction; // 0x804152fc + static THeyhoSupervisor *sSupervisor; // 0x80416f68 + static J3DAnmTexPattern *sHeyhoBtpAnm; // 0x80416f6c + static const s8 sAnmTable[7]; // 0x8041cd48 + + // Inline/Unused + //void JSUList::~JSUList(); + //void JSULink::~JSULink(); + //void scColorTypeNum; + //void scLeftDownFrame; + //void scRightDownFrame; + + // Inline + virtual THeyhoSupervisor *getSupervisor() { return sSupervisor; } // 0x802b1928 + + JSULink mLinkHeyho; // 0x170 + J3DAnmObjMaterial mAnmObj; // 0x180 + TAnmPlayer mAnmPlayer; // 0x1a0 + TPathWalk *mPathWalk; // 0x1b8 + TMapObjSubHeyho *_1bc; // 0x1bc + JGeometry::TVec3f mHeyhoPos; // 0x1c0 + JGeometry::TVec3f mHeyhoVel; // 0x1cc + JGeometry::TPos3f mHeyhoRot; // 0x1d8 + JGeometry::TPos3f _208; // 0x208 + f32 _238; // 0x238 + f32 mJumpVel; // 0x23c + f32 mSinkVel; // 0x240 + f32 _244; // 0x244 + f32 _248; // 0x248 + f32 _24c; // 0x24c + f32 _250; // 0x250 + +}; + +#endif // MAPOBJHEYHO_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 1c6992ae..2659ef7f 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -47,6 +47,7 @@ #include "Shiraiwa/Objects/MapObjDossun.h" #include "Shiraiwa/Objects/MapObjFountain.h" #include "Shiraiwa/Objects/MapObjGeyser.h" +#include "Shiraiwa/Objects/MapObjHeyho.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjSnowRock.h" @@ -131,8 +132,8 @@ GEO_OBJ_NEW_S(TTestStrItem); GEO_OBJ_NEW(TMapObjSnowRock); GEO_OBJ_NEW(TTestRollObj); GEO_OBJ_NEW(TMapObjFountain); -// GEO_OBJ_NEW(TMapObjHeyho); -// GEO_OBJ_NEW_S(TMapObjSubHeyho); +GEO_OBJ_NEW(TMapObjHeyho); +GEO_OBJ_NEW_S(TMapObjSubHeyho); // GEO_OBJ_NEW(TMapObjSanbo); // GEO_OBJ_NEW(TMapObjWlArrow); // GEO_OBJ_NEW(TMapObjSnowMan); diff --git a/src/Shiraiwa/MapObjHeyho.cpp b/src/Shiraiwa/MapObjHeyho.cpp index e69de29b..8560eb1f 100644 --- a/src/Shiraiwa/MapObjHeyho.cpp +++ b/src/Shiraiwa/MapObjHeyho.cpp @@ -0,0 +1,770 @@ +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/J3D/J3DFrameCtrl.h" +#include "JSystem/J3D/J3DModel.h" +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JGeometry/Quat.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/Course/CrsData.h" +#include "Kaneshige/RaceMgr.h" +#include "Osako/ResMgr.h" +#include "Sato/GeographyObj.h" +#include "Sato/GeographyObjMgr.h" +#include "Sato/J3DAnmObject.h" +#include "Sato/ObjCollision.h" +#include "Sato/ObjUtility.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/AnmPlayer.h" +#include "Shiraiwa/Coord3DUtil.h" +#include "Shiraiwa/Objects/MapObjHeyho.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "Shiraiwa/SiUtil.h" +#include "Yamamoto/kartCtrl.h" +#include "dolphin/mtx.h" +#include "types.h" + +TAnmInfo TMapObjHeyho::sAnmInfos[1] = { + { "/Objects/Heyho1.bca", nullptr, nullptr, 2, 0, 0, 255, 0 } +}; + +StateObserver::StateFuncSet TMapObjHeyho::sTable[7] = { + 0, &TMapObjHeyho::initFunc_Skate, &TMapObjHeyho::doFunc_Skate, + 1, &TMapObjHeyho::initFunc_Jump, &TMapObjHeyho::doFunc_Jump, + 2, &TMapObjHeyho::initFunc_Bomb, &TMapObjHeyho::doFunc_Bomb, + 3, &TMapObjHeyho::initFunc_BombEnd, &TMapObjHeyho::doFunc_BombEnd, + 4, &TMapObjHeyho::initFunc_Sink, &TMapObjHeyho::doFunc_Sink, + 5, &TMapObjHeyho::initFunc_Recover, &TMapObjHeyho::doFunc_Recover, + 6, &TMapObjHeyho::initFunc_Die, &TMapObjHeyho::doFunc_Die, +}; + +StateObserver::StateFuncSet TMapObjSubHeyho::sTable[3] = { + { 0, &TMapObjSubHeyho::initFunc_Skate, &TMapObjSubHeyho::doFunc_Skate }, + { 1, &TMapObjSubHeyho::initFunc_Spin, &TMapObjSubHeyho::doFunc_Spin }, + { 2, &TMapObjSubHeyho::initFunc_Recover, &TMapObjSubHeyho::doFunc_Recover } +}; + +TAnmInfo TMapObjSubHeyho::sAnmInfos[1] = { + { "/Objects/Heyho1.bca", nullptr, nullptr, 2, 0, 0, 255, 0 } +}; + + +f32 TMapObjHeyho::sGravity = 4.0f; +f32 TMapObjHeyho::sAccel = 0.05f; +f32 TMapObjHeyho::sJumpVel = 30.0f; +f32 TMapObjHeyho::sJumpGrv = 1.0f; +f32 TMapObjHeyho::sRotSpeed = 0.7f; +f32 TMapObjHeyho::sFirstSinkVel = -0.05f; +f32 TMapObjHeyho::sSinkAccel = 0.01f; +f32 TMapObjHeyho::sBombVelH = 40.0f; +f32 TMapObjHeyho::sBombVelV = 70.0f; +f32 TMapObjHeyho::sSlideVelH = 100.0f; +f32 TMapObjHeyho::sSlideVelV = 30.0f; +f32 TMapObjHeyho::sBombRotSpeed = 0.3f; +f32 TMapObjHeyho::sBombEndRotDecel = 0.005f; +f32 TMapObjHeyho::sAirFriction = 0.999f; + +THeyhoSupervisor *TMapObjHeyho::sSupervisor; + +J3DAnmTexPattern *TMapObjHeyho::sHeyhoBtpAnm; + +J3DAnmTexPattern *TMapObjSubHeyho::sHeyhoBtpAnm; + +const s8 TMapObjHeyho::sAnmTable[7] = { + 0, 0, 0, 0, 0, 0, 0 +}; + + +void THeyhoSupervisor::calc() { + for (JSULink *linkA = _24.getFirst(); linkA != nullptr; linkA = linkA->getNext()) { + for (JSULink *linkB = linkA; linkB != nullptr; linkB = linkB->getNext()) { + if (linkA != linkB) { + linkA->getObject()->hitCheck(linkB->getObject()); + } + } + } +} + +TMapObjHeyho::TMapObjHeyho(const CrsData::SObject &sObject) : TMapObjHioNode(sObject), StateObserver(), mLinkHeyho(this) { + NewAnmCtrl(); + createSoundMgr(); + + if (sObject.mParam2 == 1) { + _1bc = (TMapObjSubHeyho *)GetGeoObjMgr()->createSubObj(0x13ef); + _1bc->mSubHeyhoPos = &mPos; + _1bc->mSubHeyhoVel = &mVel; + _1bc->mSubHeyhoRot = &mRotMtx; + _1bc->mScale.set(mScale); + } else { + _1bc = nullptr; + } + mAnmPlayer.resetAnimations(sAnmInfos, 1); + + mPathWalk = new TPathWalk(&sObject); + + if (getSupervisor() == nullptr) { + sSupervisor = new THeyhoSupervisor; + } + + sSupervisor->_24.append(&mLinkHeyho); +} + +TMapObjHeyho::~TMapObjHeyho() { + sSupervisor = nullptr; + delete mPathWalk; +} + +void TMapObjHeyho::reset() { + f32 fVar1; + + resetObject(); + ResetState(); + setObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + _58 = 4; + + mAnmPlayer.init(mAnmCtrl, sAnmInfos, 1); + + mAnmObj.resetFrame(); + mSinkVel = 0.0f; + _238 = 0.0f; + mJumpVel = 0.0f; + _24c = 0.0f; + _250 = 0.0f; + + PSMTXIdentity(_208); + mHeyhoPos.set(mPos); + mHeyhoRot.set(mRotMtx); + + mHeyhoVel.zero(); + _248 = 0.0f; + mPathWalk->init(&mHeyhoPos, &mVel, &mHeyhoRot); + mPathWalk->reset(); + + fVar1 = mObjData->mParam1; + if (fVar1 == 0.0f) { + fVar1 = 12.0f; + } + _244 = fVar1; + + const s16 frameLimit = 3; + u16 newFrame = mObjData->mParam3; + if (newFrame >= frameLimit) { + newFrame = 0; + } + + mAnmObj.setFrame(newFrame); + + if (_1bc != nullptr) { + _1bc->mAnmObj.setFrame(newFrame); + } + mPathWalk->setParameters(fVar1, 0.2f, 0.06f, 0.001f, 0.01f); +} + +void TMapObjHeyho::calc() { + s16 updateResult = mPathWalk->update(); + if (updateResult != -1) { + checkJump(updateResult); + } + + if (checkItemHitting()) { + changeAllState(2); + } + ExecuteState(); + moveShadowModel(); + callWalkSound(); +} + +void TMapObjHeyho::callWalkSound() { + J3DFrameCtrl *anim = mAnmPlayer.mController->mTrans->getFrameCtrl(mAnmPlayer.getCurAnmNumber()); + + if (SiUtil::checkPassFrame(65.0f, anim->getFrame(), anim->getRate())) { + getSoundMgr()->setSe(0x4004B); + } + + if (SiUtil::checkPassFrame( 0.0f, anim->getFrame(), anim->getRate())) { + getSoundMgr()->setSe(0x4004A); + } +} + +bool TMapObjHeyho::checkItemHitting() { + bool hit = false; + + if (tstItemHitting()) { + ItemObj* item = mColItemObj; + + switch (item->mItemKind) { + case 1: + case 7: + case 8: + _24c = sBombVelH; + _250 = sBombVelV; + mHeyhoVel.set(item->mPos); + hit = true; + break; + + case 0: + case 2: + case 9: + _24c = sSlideVelH; + _250 = sSlideVelV; + mHeyhoVel.set(item->mPos); + hit = true; + break; + } + } + + if (!hit && _1bc != nullptr) { + if (_1bc->checkItemHitting()) { + hit = true; + } + } + + return hit; +} + +void TMapObjHeyho::checkJump(u16 param_1) { + if (RCMGetCourse()->getCrsData()->getPointData(mObjData->mPathID, param_1)->linkPoint) { + setState(1); + } +} + +const char *TMapObjHeyho::getBmdFileName() { + static const char *cBmdName = "/Objects/Heyho1.bmd"; + return cBmdName; +} + +const char *TMapObjHeyho::getShadowBmdFileName() { + static const char *cShadowBmdName = "/Objects/Heyho1Shadow.bmd"; + return cShadowBmdName; +} + +void TMapObjHeyho::loadAnimation() { + J3DModelData *modelData = *mModel.mModelData; + TAnmPlayer::loadAnimations(sAnmInfos, 1, modelData, ResMgr::mcArcCourse); + void *ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/Heyho1.btp"); + mAnmObj.setupTexPatternAnmData(&sHeyhoBtpAnm, modelData, ptrCourseArc); +} + +void TMapObjHeyho::createModel(JKRSolidHeap *jkrSolidHeap, u32 p2) { + mModel.createDifferedModel(jkrSolidHeap, p2, 0x20000, 0); + TAnmPlayer::registAnimations(mAnmCtrl, &mModel, sAnmInfos, 1); + mAnmObj.setExModel(&mModel); + mAnmObj.setAnmBase(sHeyhoBtpAnm); + mAnmObj.initFrameCtrl(mAnmObj.getAnmBase()); +} + +void TMapObjHeyho::createColModel(J3DModelData *modelData) { + f32 scaleXZ = mScale.x > mScale.z + ? mScale.x + : mScale.z; + + f32 max = scaleXZ > mScale.y + ? scaleXZ + : mScale.y; + + createBoundsCylinder(modelData, 140.0f * (scaleXZ / max), + 320.0f * (mScale.y / max) + ); +} + +void TMapObjHeyho::InitExec() { Observer_FindAndInit(TMapObjHeyho, 7); } + +void TMapObjHeyho::MoveExec() { Observer_FindAndExec(TMapObjHeyho, 7); } + +void TMapObjHeyho::update() { + mAnmObj.anmFrameProc(); + setModelMatrixAndScale(); + mModel.update(0); +} + +void TMapObjHeyho::changeAllState(u16 state) { + #line 386 + JUT_MINMAX_ASSERT(0, state, 7); + setState((u16)state); + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[state]) { + mAnmPlayer._11 = sAnmTable[state]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } +} + +void TMapObjHeyho::doKartColCallBack(int kartNo) { + KartBody *kart = GetKartCtrl()->getKartBody(kartNo); + + if (kart->mCarStatus & 0x40000) { + ObjUtility::getKartPos(kartNo, &mHeyhoVel); + setState(2); + + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[2]) { + mAnmPlayer._11 = sAnmTable[2]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } + } +} + +void TMapObjHeyho::initFunc_Skate() { + mPathWalk->_94 = 1; + if (!mAnmCtrl->IsAvailableTrans()) { + return; + } + mAnmCtrl->StopTrans(); +} + +void TMapObjHeyho::doFunc_Skate() { + mPos.set(mHeyhoPos); + mRotMtx.set(mHeyhoRot); +} + +void TMapObjHeyho::initFunc_Jump() { + _238 = 0.0f; + mJumpVel = sJumpVel; + + mRotMtx.set(mHeyhoRot); + PSMTXIdentity(_208); + + const f32 angle = sRotSpeed; + const f32 s = sinf(angle); + const f32 c = cosf(angle); + _208[1][1] = 1.0f; + _208[0][0] = c; + _208[0][2] = s; + _208[2][0] = -s; + _208[2][2] = c; + _208[2][1] = 0.0f; + _208[1][2] = 0.0f; + _208[1][0] = 0.0f; + _208[0][1] = 0.0f; + + if (mAnmCtrl->IsAvailableTrans()) { + mAnmCtrl->mTrans->setFlag(); + } + if (_1bc != nullptr) { + _1bc->setState(1); + } + + getSoundMgr()->setSe(0x4004c); +} + +void TMapObjHeyho::doFunc_Jump() { + mJumpVel -= sJumpGrv; + _238 += mJumpVel; + if (_238 < 0.0f) { + _238 = 0.0f; + mHeyhoRot.set(mRotMtx); + if (mAnmCtrl->mTrans != nullptr) { + mAnmCtrl->mTrans->resetFlag(); + } + mPathWalk->_90 = _244 * 0.5f; + if (_1bc != nullptr) { + _1bc->setState(2); + } + setState(4); + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[4]) { + mAnmPlayer._11 = sAnmTable[4]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } + } + + mPos.set(mHeyhoPos.x, mHeyhoPos.y + _238, mHeyhoPos.z); + PSMTXConcat(mRotMtx, _208, mRotMtx); +} + +void TMapObjHeyho::initFunc_Bomb() { + mPathWalk->_94 = 0; + + JGeometry::TVec3f local_38; + local_38.sub(mPos, mHeyhoVel); + local_38.normalize(); + + local_38.y = 0.0f; + local_38.setLength(_24c); + + local_38.y = _250; + mVel.set(local_38); + + mRotMtx.set(mHeyhoRot); + PSMTXIdentity(_208); + + const f32 angle = sBombRotSpeed; + const f32 s = sinf(angle); + const f32 c = cosf(angle); + _208[1][1] = 1.0f; + _208[0][0] = c; + _208[0][2] = s; + _208[2][0] = -s; + _208[2][2] = c; + _208[2][1] = 0.0f; + _208[1][2] = 0.0f; + _208[1][0] = 0.0f; + _208[0][1] = 0.0f; + + if (mAnmCtrl->IsAvailableTrans()) { + mAnmCtrl->mTrans->setFlag(); + } + if (_1bc != nullptr) { + _1bc->setState(1); + } +} + +void TMapObjHeyho::doFunc_Bomb() { + PSMTXConcat(mRotMtx, _208, mRotMtx); + + mVel.scale(sAirFriction); + mVel.y -= sGravity; + + JGeometry::TVec3f oldPos(mPos); + mPos.add(mVel); + + CrsGround ground(RCMGetCourse()); + ground.search(mPos, oldPos); + + JGeometry::TVec3f wallNormal; + f32 normalisedWall = ground.getWallNormal(&wallNormal, nullptr); + if (normalisedWall > -1.0f) { + mPos.scaleAdd(normalisedWall, wallNormal, mPos); + } + + f32 groundHeight = ground.getHeight(); + + if (mPos.y < groundHeight) { + ground.search(oldPos); + + switch (ground.getAttribute()) { + case 0x05: + case 0x0A: + case 0x0E: + case 0x0F: + case 0xFF: { + setState(6); + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[6]) { + mAnmPlayer._11 = sAnmTable[6]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } + break; + } + + default: { + mPos.y = groundHeight; + mHeyhoPos.set(mPos); + mHeyhoRot.set(mRotMtx); + + mVel.zero(); + mPathWalk->_90 = 0.0f; + + setState(3); + + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[3]) { + mAnmPlayer._11 = sAnmTable[3]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } + + break; + } + } + } +} + +void TMapObjHeyho::initFunc_BombEnd() { + _248 = sBombRotSpeed; +} + +void TMapObjHeyho::doFunc_BombEnd() { + JGeometry::TVec3f local_4c; + JGeometry::TVec3f local_58; + JGeometry::TPos3f auStack_40; + + _248 -= sBombEndRotDecel; + if (_248 <= 0.0f) { + _248 = 0.0f; + mRotMtx.getZDir(local_4c); + local_4c.y = 0.0f; + local_4c.normalize(); + mRotMtx.getYDir(local_58); + local_58.x = 0.0f; + local_58.normalize(); + mHeyhoRot.set(mRotMtx); + mPathWalk->_94 = 1; + mPathWalk->forceTurn(local_58, local_4c); + if (_1bc != nullptr) { + _1bc->setState(2); + } + setState(5); + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[5]) { + mAnmPlayer._11 = sAnmTable[5]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } + } else { + PSMTXIdentity(auStack_40); + PSMTXRotRad(auStack_40, 'y', _248); + PSMTXConcat(mRotMtx, auStack_40, mRotMtx); + } +} + +void TMapObjHeyho::initFunc_Sink() { + mSinkVel = sFirstSinkVel; + getSoundMgr()->setSe(0x4005a); +} + +void TMapObjHeyho::doFunc_Sink() { + mSinkVel += sSinkAccel; + mRotMtx[3][1] += mSinkVel; + + if (mRotMtx[3][1] > 1.0f) { + mRotMtx[3][1] = 1.0f; + } + + f32 walkPos = mPathWalk->_90; + walkPos += sAccel; + + if (walkPos > _244) { + walkPos = _244; + + if (mRotMtx[3][1] >= 1.0f) { + setState(0); + + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[0]) { + mAnmPlayer._11 = sAnmTable[0]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } + } + } + + mPathWalk->_90 = walkPos; + + mPos.set(mHeyhoPos); + mRotMtx.set(mHeyhoRot); +} + +void TMapObjHeyho::initFunc_Recover() { + mPathWalk->_94 = 1; + if (!mAnmCtrl->IsAvailableTrans()) { + return; + } + mAnmCtrl->StopTrans(); +} + +void TMapObjHeyho::doFunc_Recover() { + f32 walkPos = mPathWalk->_90; + walkPos += sAccel; + + if (walkPos > _244) { + walkPos = _244; + + if (mRotMtx[3][1] >= 1.0f) { + setState(0); + + if (mAnmPlayer.getCurAnmNumber() != sAnmTable[0]) { + mAnmPlayer._11 = sAnmTable[0]; + mAnmPlayer._10 = true; + mAnmPlayer._e |= 1; + } + } + } + mPathWalk->_90 = walkPos; + mPos.set(mHeyhoPos); + mRotMtx.set(mHeyhoRot); +} + +void TMapObjHeyho::initFunc_Die() { + mPathWalk->_94 = 0; + if (mAnmCtrl->IsAvailableTrans()) { + mAnmCtrl->mTrans->setFlag(); + } + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + setObjFlagHidding(); +} + +void TMapObjHeyho::doFunc_Die() {} + +// FIX: Register mismatch. +void TMapObjHeyho::hitCheck(TMapObjHeyho* heyho) { + JGeometry::TVec3f heyhoPos(heyho->mPos); + JGeometry::TVec3f delta; + + if (getBounds(0)->IsHitCylinder(mPos, heyhoPos, *(ObjColCylinder *)heyho->getBounds(0))) { + delta.sub(mPos, heyhoPos); + delta.normalize(); + delta.scale(getBounds(0)->getBoundDepth()); + + mPos.add(delta); + mHeyhoPos.set(mPos); + } +} + +TMapObjSubHeyho::TMapObjSubHeyho() : GeographyObj(0x13ef) { + NewAnmCtrl(); + TAnmPlayer::resetAnimations(sAnmInfos, 1); +} + +void TMapObjSubHeyho::reset() { + setObjFlagCheckItemHitting(); + setAllCheckKartHitFlag(); + _58 = 4; + mAnmCtrl->Reset(); + mAnmObj.resetFrame(); + _188.set(250.0f, 0.0f, 0.0f); + ResetState(); +} + +bool TMapObjSubHeyho::checkItemHitting() { + bool isItemHitting = false; + if (tstItemHitting()) { + switch (mColItemObj->mItemKind) { + case 0: + case 1: + case 2: + case 7: + case 8: + case 9: + isItemHitting = true; + break; + } + } + return isItemHitting; +} + +void TMapObjSubHeyho::InitExec() { Observer_FindAndInit(TMapObjSubHeyho, 3); } + +void TMapObjSubHeyho::MoveExec() { Observer_FindAndExec(TMapObjSubHeyho, 3); } + +void TMapObjSubHeyho::calc() { + mRotMtx.set(*mSubHeyhoRot); + ExecuteState(); + moveShadowModel(); +} + +void TMapObjSubHeyho::initFunc_Skate() { + setAllCheckKartHitFlag(); + setObjFlagCheckItemHitting(); +} + +void TMapObjSubHeyho::doFunc_Skate() { + JGeometry::TVec3f newPos; + JGeometry::TPos3f mtxFront; + + makeFrontMtx(&mtxFront); + PSMTXMultVecSR(mtxFront, &_188, &newPos); + mPos.add(*mSubHeyhoPos, newPos); +} + + +void TMapObjSubHeyho::makeFrontMtx(JGeometry::TPos3f *mtx) { + JGeometry::TVec3f dirX; + JGeometry::TVec3f dirY; + JGeometry::TVec3f dirZ; + + if (mSubHeyhoVel->isZero()) { + mRotMtx.getZDir(dirZ); + if (dirZ.isZero()) { + dirZ.set(0.0f, 0.0f, 1.0f); + } + } else { + dirZ.set(*mSubHeyhoVel); + } + dirZ.normalize(); + dirY.set(0.0f, 1.0f, 0.0f); + dirX.cross(dirY, dirZ); + dirX.normalize(); + mtx->setXYZDir(dirX, dirY, dirZ); +} + +void TMapObjSubHeyho::initFunc_Spin() { + _194.set(*mSubHeyhoRot); + clrAllCheckKartHitFlag(); + clrObjFlagCheckItemHitting(); +} + +void TMapObjSubHeyho::doFunc_Spin() { + JGeometry::TVec3f newPos; + + PSMTXMultVecSR(_194, &_188, &newPos); + mPos.add(*mSubHeyhoPos, newPos); +} + +void TMapObjSubHeyho::initFunc_Recover() { + _1c4 = 0.0f; + _194.zeroTrans(); +} + +// FIX: Register mismatch. +void TMapObjSubHeyho::doFunc_Recover() { + JGeometry::TQuat4f local_4c(0.0f, 0.0f, 0.0f, 1.0f); + _194.getQuat(local_4c); + local_4c.normalize(local_4c); + JGeometry::TPos3f local_3c; + makeFrontMtx(&local_3c); + JGeometry::TQuat4f local_5c(0.0f, 0.0f, 0.0f, 1.0f); + local_3c.getQuat(local_5c); + local_5c.normalize(local_5c); + + // FIX: Should this be an inlined slerp/nlerp? + local_4c.x = _1c4 * local_4c.x + (local_5c.x - local_4c.x); + local_4c.y = _1c4 * local_4c.y + (local_5c.y - local_4c.y); + local_4c.z = _1c4 * local_4c.z + (local_5c.z - local_4c.z); + local_4c.w = _1c4 * local_4c.w + (local_5c.w - local_4c.w); + + local_4c.normalize(local_4c); + local_3c.setQuat(local_4c); + JGeometry::TVec3f local_68; + PSMTXMultVecSR(local_3c, &_188, &local_68); + mPos.add(*mSubHeyhoPos, local_68); + _1c4 += 0.01f; + if (_1c4 >= 1.0f) { + setState(0); + } +} + +const char *TMapObjSubHeyho::getBmdFileName() { + static const char *cBmdName = "/Objects/Heyho1.bmd"; + return cBmdName; +} + +const char *TMapObjSubHeyho::getShadowBmdFileName() { + static const char *cShadowBmdName = "/Objects/Heyho1Shadow.bmd"; + return cShadowBmdName; +} + +void TMapObjSubHeyho::update() { + mAnmObj.anmFrameProc(); + setModelMatrixAndScale(); + mModel.update(0); +} + +void TMapObjSubHeyho::loadAnimation() { + J3DModelData *modelData = *mModel.mModelData; + TAnmPlayer::loadAnimations(sAnmInfos, 1, modelData, ResMgr::mcArcCourse); + void *ptrCourseArc = ObjUtility::getPtrCourseArc("/Objects/Heyho1.btp"); + mAnmObj.setupTexPatternAnmData(&sHeyhoBtpAnm, modelData, ptrCourseArc); +} + +void TMapObjSubHeyho::createModel(JKRSolidHeap *jkrSolidHeap, u32 p2) { + mModel.createDifferedModel(jkrSolidHeap, p2, 0x20000, 0); + TAnmPlayer::registAnimations(mAnmCtrl, &mModel, sAnmInfos, 1); + mAnmObj.setExModel(&mModel); + mAnmObj.setAnmBase(sHeyhoBtpAnm); + mAnmObj.initFrameCtrl(mAnmObj.getAnmBase()); +} + +void TMapObjSubHeyho::createColModel(J3DModelData *modelData) { + f32 scaleXZ = mScale.x > mScale.z + ? mScale.x + : mScale.z; + + f32 max = scaleXZ > mScale.y + ? scaleXZ + : mScale.y; + + createBoundsCylinder(modelData, 140.0f * (scaleXZ / max), + 320.0f * (mScale.y / max) + ); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 0ac2fe7f59d30e1b796559e22f8dd5b1ac4149cd Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 17:53:37 +1000 Subject: [PATCH 22/29] GeoObjMgr - Implement MapObjWluArrow. --- include/Shiraiwa/Objects/MapObjWluArrow.h | 43 +++++++++ src/Sato/GeographyObjMgr.cpp | 5 +- src/Shiraiwa/MapObjWluArrow.cpp | 109 ++++++++++++++++++++++ 3 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 include/Shiraiwa/Objects/MapObjWluArrow.h diff --git a/include/Shiraiwa/Objects/MapObjWluArrow.h b/include/Shiraiwa/Objects/MapObjWluArrow.h new file mode 100644 index 00000000..55f2f61f --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjWluArrow.h @@ -0,0 +1,43 @@ +#ifndef MAPOBJWLUARROW_H +#define MAPOBJWLUARROW_H + +#include "JSystem/J3D/J3DAnmTransform.h" +#include "JSystem/J3D/J3DMtxCalc.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/J3DAnmObject.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjWlArrow : public TMapObjHioNode { // Autogenerated +public: + TMapObjWlArrow(const CrsData::SObject &); + virtual ~TMapObjWlArrow(); + virtual void loadAnimation(); + virtual void createModel(JKRSolidHeap *, u32); + virtual void reset(); + virtual void calc(); + virtual void update(); + virtual const char *getBmdFileName(); + + static J3DAnmTextureSRTKey *sWlArrowBtkAnm; // 0x80416f08 + static J3DAnmTransform *sWlArrowBckAnmTrans; // 0x80416de0 + static J3DMtxCalc *sWlArrowBckMtxCalc; // 0x80416de4 + + J3DAnmObjMaterial mAnmObjMat; +}; // class TMapObjWluArrow + +class TMapObjWluSearchLight : public TMapObjHioNode { +public: + TMapObjWluSearchLight(const CrsData::SObject &); + virtual ~TMapObjWluSearchLight(); + virtual void loadAnimation(); + virtual void createModel(JKRSolidHeap *, u32); + virtual void reset(); + virtual void calc() {} + virtual const char *getBmdFileName(); + + static J3DAnmTransform *sWlScLightBckAnmTrans; // 0x80416de0 + static J3DMtxCalc *sWlScLightBckMtxCalc; // 0x80416de4 +}; + +#endif // MAPOBJWLUARROW_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 2659ef7f..0433331a 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -52,6 +52,7 @@ #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjSnowRock.h" #include "Shiraiwa/Objects/MapObjWanwan.h" +#include "Shiraiwa/Objects/MapObjWluArrow.h" #include "Shiraiwa/TestRollObj.h" #include "Shiraiwa/TestString.h" #include "Sato/GeographyObjMgr.h" @@ -135,7 +136,7 @@ GEO_OBJ_NEW(TMapObjFountain); GEO_OBJ_NEW(TMapObjHeyho); GEO_OBJ_NEW_S(TMapObjSubHeyho); // GEO_OBJ_NEW(TMapObjSanbo); -// GEO_OBJ_NEW(TMapObjWlArrow); +GEO_OBJ_NEW(TMapObjWlArrow); // GEO_OBJ_NEW(TMapObjSnowMan); // GEO_OBJ_NEW(TMapObjIceBlock); // GEO_OBJ_NEW(TMapObjNoMove); @@ -191,7 +192,7 @@ GEO_OBJ_NEW(TMapObjDemoFountain); // GEO_OBJ_NEW(TMapObjPeachTree2); // GEO_OBJ_NEW(TMapObjYoshiHeli); GEO_OBJ_NEW(TMapObjDesertTree); -// GEO_OBJ_NEW(TMapObjWluSearchLight); +GEO_OBJ_NEW(TMapObjWluSearchLight); // GEO_OBJ_NEW(TMapObjVentilator); // GEO_OBJ_NEW_S(TShineArrow); GEO_OBJ_NEW(TMapObjUFO); diff --git a/src/Shiraiwa/MapObjWluArrow.cpp b/src/Shiraiwa/MapObjWluArrow.cpp index e69de29b..916a2d4e 100644 --- a/src/Shiraiwa/MapObjWluArrow.cpp +++ b/src/Shiraiwa/MapObjWluArrow.cpp @@ -0,0 +1,109 @@ +#include "JSystem/J3D/J3DAnmTextureSRTKey.h" +#include "JSystem/J3D/J3DAnmTransform.h" +#include "JSystem/J3D/J3DMtxCalc.h" +#include "Sato/AnmController.h" +#include "Sato/ObjUtility.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" +#include "Shiraiwa/Objects/MapObjWluArrow.h" + +J3DAnmTextureSRTKey *TMapObjWlArrow::sWlArrowBtkAnm; +J3DAnmTransform *TMapObjWlArrow::sWlArrowBckAnmTrans; +J3DMtxCalc *TMapObjWlArrow::sWlArrowBckMtxCalc; + +J3DAnmTransform *TMapObjWluSearchLight::sWlScLightBckAnmTrans; +J3DMtxCalc *TMapObjWluSearchLight::sWlScLightBckMtxCalc; + + +TMapObjWlArrow::TMapObjWlArrow(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { + NewAnmCtrl(); +} + +TMapObjWlArrow::~TMapObjWlArrow() {} + +const char *TMapObjWlArrow::getBmdFileName() { + static const char *cBmdName = "/Objects/Wlarrow1.bmd"; + return cBmdName; +} + +void TMapObjWlArrow::reset() { + GeographyObj::resetObject(); + clrObjFlagHidding(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + mAnmObjMat.getFrameCtrl()->reset(); + getAnmCtrl()->Reset(); +} + +void TMapObjWlArrow::createModel(JKRSolidHeap *heap, u32 p2) { + mModel.createDifferedModel(heap, p2, 0x200, 0); + + mAnmObjMat.setExModel(&mModel); + mAnmObjMat.setAnmBase(sWlArrowBtkAnm); + mAnmObjMat.initFrameCtrl(mAnmObjMat.mAnmBase); + + AnmController *anmCtrl = mAnmCtrl; + AnmControlTrans *anmCtrlTrans = new AnmControlTrans(); + + anmCtrl->mTrans = anmCtrlTrans; + anmCtrlTrans = anmCtrl->mTrans; + anmCtrlTrans->initAnm(1, &mModel); + + mAnmCtrl->mTrans->registration(0, sWlArrowBckAnmTrans, sWlArrowBckMtxCalc); + getAnmCtrl()->getFrameCtrl(0)->setAttribute(2); +} + +void TMapObjWlArrow::loadAnimation() { + J3DModelData *modelData = mModel.getModelData(); + J3DAnmObjTrans::setupTransAnmData(&sWlArrowBckAnmTrans, &sWlArrowBckMtxCalc, modelData, ObjUtility::getPtrCourseArc("/Objects/Wlarrow1.bck")); + J3DAnmObjMaterial::setupTexSRTAnmData(&sWlArrowBtkAnm, modelData, ObjUtility::getPtrCourseArc("/Objects/Wlarrow1.btk")); +} + +void TMapObjWlArrow::calc() { + mAnmObjMat.update(); +} + +void TMapObjWlArrow::update() { + mAnmObjMat.anmFrameProc(); + GeographyObj::update(); +} + + +TMapObjWluSearchLight::TMapObjWluSearchLight(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { + NewAnmCtrl(); +} + +TMapObjWluSearchLight::~TMapObjWluSearchLight() {} + +const char *TMapObjWluSearchLight::getBmdFileName() { + static const char *cBmdName = "/Objects/Wa_Search1.bmd"; + return cBmdName; +} + +void TMapObjWluSearchLight::reset() { + GeographyObj::resetObject(); + clrObjFlagHidding(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + getAnmCtrl()->Reset(); +} + +void TMapObjWluSearchLight::createModel(JKRSolidHeap *heap, u32 p2) { + mModel.createModel(heap, p2, 0); + + AnmController *anmCtrl = mAnmCtrl; + AnmControlTrans *anmCtrlTrans = new AnmControlTrans(); + + anmCtrl->mTrans = anmCtrlTrans; + anmCtrlTrans = anmCtrl->mTrans; + anmCtrlTrans->initAnm(1, &mModel); + + mAnmCtrl->mTrans->registration(0, sWlScLightBckAnmTrans, sWlScLightBckMtxCalc); + getAnmCtrl()->getFrameCtrl(0)->setAttribute(2); +} + +void TMapObjWluSearchLight::loadAnimation() { + J3DModelData *modelData = mModel.getModelData(); + J3DAnmObjTrans::setupTransAnmData(&sWlScLightBckAnmTrans, &sWlScLightBckMtxCalc, modelData, ObjUtility::getPtrCourseArc("/Objects/Wa_Search1.bck")); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 80cc7668ff306690caff259d2c819017d510bfb0 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 18:27:41 +1000 Subject: [PATCH 23/29] GeoObjMgr - Implement TMapObjSnowMan. --- include/Shiraiwa/Objects/MapObjSnowMan.h | 26 +++++++++++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/MapObjSnowMan.cpp | 49 ++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjSnowMan.h diff --git a/include/Shiraiwa/Objects/MapObjSnowMan.h b/include/Shiraiwa/Objects/MapObjSnowMan.h new file mode 100644 index 00000000..fef46d7c --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjSnowMan.h @@ -0,0 +1,26 @@ +#ifndef MAPOBJSNOWMAN_H +#define MAPOBJSNOWMAN_H + +#include "JSystem/J3D/J3DSkinDeform.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "Kaneshige/Course/CrsData.h" +#include "Sato/J3DAnmObject.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjSnowMan : public TMapObjHioNode { // Autogenerated +public: + TMapObjSnowMan(const CrsData::SObject &); // 0x802b6e50 + virtual ~TMapObjSnowMan(); // 0x802b6edc + virtual void loadAnimation(); // 0x802b70c4 + virtual void createModel(JKRSolidHeap *, u32); // 0x802b7050 + virtual void reset(); // 0x802b6fd4 + virtual void calc(); // 0x802b7118 + virtual void update(); // 0x802b711c + virtual const char *getBmdFileName(); // 0x802b6fac + + static J3DDeformData *sSnowManBlsAnmData; // 0x80416fc8 + static J3DAnmCluster *sSnowManBlkAnmData; // 0x80416fcc + + J3DAnmObjCluster _14c; +}; // class MapObjSnowMan +#endif // MAPOBJSNOWMAN_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 0433331a..3d33b036 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -50,6 +50,7 @@ #include "Shiraiwa/Objects/MapObjHeyho.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" +#include "Shiraiwa/Objects/MapObjSnowMan.h" #include "Shiraiwa/Objects/MapObjSnowRock.h" #include "Shiraiwa/Objects/MapObjWanwan.h" #include "Shiraiwa/Objects/MapObjWluArrow.h" @@ -137,7 +138,7 @@ GEO_OBJ_NEW(TMapObjHeyho); GEO_OBJ_NEW_S(TMapObjSubHeyho); // GEO_OBJ_NEW(TMapObjSanbo); GEO_OBJ_NEW(TMapObjWlArrow); -// GEO_OBJ_NEW(TMapObjSnowMan); +GEO_OBJ_NEW(TMapObjSnowMan); // GEO_OBJ_NEW(TMapObjIceBlock); // GEO_OBJ_NEW(TMapObjNoMove); GEO_OBJ_NEW(GeoKuribo); diff --git a/src/Shiraiwa/MapObjSnowMan.cpp b/src/Shiraiwa/MapObjSnowMan.cpp index e69de29b..a21e85c7 100644 --- a/src/Shiraiwa/MapObjSnowMan.cpp +++ b/src/Shiraiwa/MapObjSnowMan.cpp @@ -0,0 +1,49 @@ +#include "Shiraiwa/Objects/MapObjSnowMan.h" +#include "Sato/ObjUtility.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +J3DDeformData *TMapObjSnowMan::sSnowManBlsAnmData; +J3DAnmCluster *TMapObjSnowMan::sSnowManBlkAnmData; + + +TMapObjSnowMan::TMapObjSnowMan(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) {} + +TMapObjSnowMan::~TMapObjSnowMan() {} + +const char *TMapObjSnowMan::getBmdFileName() { + static const char *cBmdName = "/Objects/Snowman1.bmd"; + return cBmdName; +} + +void TMapObjSnowMan::reset() { + GeographyObj::resetObject(); + clrObjFlagHidding(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + _14c.resetFrame(); +} + + +void TMapObjSnowMan::createModel(JKRSolidHeap *heap, u32 p2) { + mModel.createModel(heap, p2, false); + J3DAnmObjCluster::setDeformData(&mModel, sSnowManBlsAnmData, false); + _14c.setExModel(&mModel, sSnowManBlsAnmData); + _14c.attach(sSnowManBlkAnmData); + _14c.getFrameCtrl()->setAttribute(2); +} + +void TMapObjSnowMan::loadAnimation() { + J3DDeformData *snowmanDeformData = (J3DDeformData *)ObjUtility::getPtrCourseArc("/Objects/Snowman1.bls"); + J3DAnmObjCluster::loadClusterData(&sSnowManBlsAnmData, snowmanDeformData); + J3DAnmCluster *snowmanClusterData = (J3DAnmCluster *)ObjUtility::getPtrCourseArc("/Objects/Snowman1.blk"); + J3DAnmObjCluster::loadClusterAnmData(&sSnowManBlkAnmData, snowmanClusterData); +} + +void TMapObjSnowMan::calc() {} + +void TMapObjSnowMan::update() { + _14c.update(); + GeographyObj::update(); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From a9c669837246a29249ef3d2b23f80d3d9938e9cf Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 18:43:14 +1000 Subject: [PATCH 24/29] GeoObjMgr - Add TMapObjIceBlock. --- src/Sato/GeographyObjMgr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 3d33b036..4f0ebd75 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -48,6 +48,7 @@ #include "Shiraiwa/Objects/MapObjFountain.h" #include "Shiraiwa/Objects/MapObjGeyser.h" #include "Shiraiwa/Objects/MapObjHeyho.h" +#include "Shiraiwa/Objects/MapObjIceBlock.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjSnowMan.h" @@ -139,7 +140,7 @@ GEO_OBJ_NEW_S(TMapObjSubHeyho); // GEO_OBJ_NEW(TMapObjSanbo); GEO_OBJ_NEW(TMapObjWlArrow); GEO_OBJ_NEW(TMapObjSnowMan); -// GEO_OBJ_NEW(TMapObjIceBlock); +GEO_OBJ_NEW(TMapObjIceBlock); // GEO_OBJ_NEW(TMapObjNoMove); GEO_OBJ_NEW(GeoKuribo); // GEO_OBJ_NEW(TMapObjSun); From 64929042c44c2ba181bdd5a3ed2cb47181ddfe39 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 18:53:59 +1000 Subject: [PATCH 25/29] GeoObjMgr - Implement TMapObjNoMove. --- include/Shiraiwa/Objects/MapObjNoMove.h | 19 +++++++++++++++ src/Sato/GeographyObjMgr.cpp | 3 ++- src/Shiraiwa/MapObjNoMove.cpp | 32 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjNoMove.h diff --git a/include/Shiraiwa/Objects/MapObjNoMove.h b/include/Shiraiwa/Objects/MapObjNoMove.h new file mode 100644 index 00000000..6d5dcb08 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjNoMove.h @@ -0,0 +1,19 @@ +#ifndef MAPOBJNOMOVE_H +#define MAPOBJNOMOVE_H + +#include "Kaneshige/Course/CrsData.h" +#include "Sato/GeographyObj.h" + + +class TMapObjNoMove : public GeographyObj { +public: + TMapObjNoMove(const CrsData::SObject &); // 0x8029c390 + virtual ~TMapObjNoMove() {} // 0x8029c3d8 + virtual void reset(); // 0x8029c458 + virtual const char *getBmdFileName(); // 0x8029c4a4 + virtual void calc() {} // 0x8029c4f0 + + static GeoAnmTableEntry sObjList[4]; // 0x803a4d40 + +}; // class TMapObjNoMove +#endif // MAPOBJNOMOVE_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 4f0ebd75..2d6aa536 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -49,6 +49,7 @@ #include "Shiraiwa/Objects/MapObjGeyser.h" #include "Shiraiwa/Objects/MapObjHeyho.h" #include "Shiraiwa/Objects/MapObjIceBlock.h" +#include "Shiraiwa/Objects/MapObjNoMove.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjSnowMan.h" @@ -141,7 +142,7 @@ GEO_OBJ_NEW_S(TMapObjSubHeyho); GEO_OBJ_NEW(TMapObjWlArrow); GEO_OBJ_NEW(TMapObjSnowMan); GEO_OBJ_NEW(TMapObjIceBlock); -// GEO_OBJ_NEW(TMapObjNoMove); +GEO_OBJ_NEW(TMapObjNoMove); GEO_OBJ_NEW(GeoKuribo); // GEO_OBJ_NEW(TMapObjSun); // GEO_OBJ_NEW(TMapObjBubble); diff --git a/src/Shiraiwa/MapObjNoMove.cpp b/src/Shiraiwa/MapObjNoMove.cpp index e69de29b..73b674e7 100644 --- a/src/Shiraiwa/MapObjNoMove.cpp +++ b/src/Shiraiwa/MapObjNoMove.cpp @@ -0,0 +1,32 @@ +#include "Shiraiwa/Objects/MapObjNoMove.h" +#include "Sato/GeographyObj.h" + +// TODO: Does a structure like this already exist? +GeoAnmTableEntry TMapObjNoMove::sObjList[4] = { + { 4505, "/Objects/DonkyWood.bmd" }, + { 4208, "/Objects/Wl_Dokan1.bmd" }, + { 5107, "/Objects/Lights1.bmd" }, + { 5004, "/Objects/DeBalloon1.bmd" } +}; + +TMapObjNoMove::TMapObjNoMove(const CrsData::SObject &sObject) : GeographyObj(sObject) { + setObjFlagSimpleDraw(); +} + +const char *TMapObjNoMove::getBmdFileName() { + for (int i = 0; i < 4; i++) { + if (mObjData->objID == sObjList[i]._0) { + return sObjList[i].fileName; + } + } + return NULL; +}; + +void TMapObjNoMove::reset() { + GeographyObj::resetObject(); + clrObjFlagCheckGeoHitting(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 89d23fdefd006368cce0071ebef29d76ea0fe8ea Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 18:56:34 +1000 Subject: [PATCH 26/29] GeoObjMgr - Implement TMapObjSun. --- include/Shiraiwa/Objects/MapObjSun.h | 21 ++++++++++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/MapObjSun.cpp | 48 ++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjSun.h diff --git a/include/Shiraiwa/Objects/MapObjSun.h b/include/Shiraiwa/Objects/MapObjSun.h new file mode 100644 index 00000000..fefa6b41 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjSun.h @@ -0,0 +1,21 @@ +#ifndef MAPOBJSUN_H +#define MAPOBJSUN_H + +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjSun : public TMapObjHioNode { +public: + TMapObjSun(const CrsData::SObject &); // 0x802b9a40 + virtual ~TMapObjSun(); // 0x802b9acc + virtual const char *getBmdFileName(); // 0x802b9b9c + virtual void reset(); // 0x802b9bc4 + virtual void createModel(JKRSolidHeap *, u32); // 0x802b9c40 + virtual void loadAnimation(); // 0x802b9ca0 + virtual void calc(); // 0x802b9ce8 + virtual void update(); // 0x802b9d0c + + static J3DAnmTextureSRTKey *sSunBtkAnm; // 0x80416ff8 + + J3DAnmObjMaterial mAnmObjMat; +}; // class TMapObjSun +#endif // MAPOBJSUN_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 2d6aa536..f18bd6dc 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -54,6 +54,7 @@ #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjSnowMan.h" #include "Shiraiwa/Objects/MapObjSnowRock.h" +#include "Shiraiwa/Objects/MapObjSun.h" #include "Shiraiwa/Objects/MapObjWanwan.h" #include "Shiraiwa/Objects/MapObjWluArrow.h" #include "Shiraiwa/TestRollObj.h" @@ -144,7 +145,7 @@ GEO_OBJ_NEW(TMapObjSnowMan); GEO_OBJ_NEW(TMapObjIceBlock); GEO_OBJ_NEW(TMapObjNoMove); GEO_OBJ_NEW(GeoKuribo); -// GEO_OBJ_NEW(TMapObjSun); +GEO_OBJ_NEW(TMapObjSun); // GEO_OBJ_NEW(TMapObjBubble); // GEO_OBJ_NEW(TMapObjDesun); // GEO_OBJ_NEW(TMapObjSandPillar); diff --git a/src/Shiraiwa/MapObjSun.cpp b/src/Shiraiwa/MapObjSun.cpp index e69de29b..60a916fd 100644 --- a/src/Shiraiwa/MapObjSun.cpp +++ b/src/Shiraiwa/MapObjSun.cpp @@ -0,0 +1,48 @@ +#include "Shiraiwa/Objects/MapObjSun.h" +#include "Sato/GeographyObj.h" +#include "Sato/J3DAnmObject.h" +#include "Sato/ObjUtility.h" + +J3DAnmTextureSRTKey *TMapObjSun::sSunBtkAnm; + +TMapObjSun::TMapObjSun(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { + +} + +TMapObjSun::~TMapObjSun() {} + +const char *TMapObjSun::getBmdFileName() { + static const char *cBmdName = "/Objects/sun.bmd"; + return cBmdName; +} + +void TMapObjSun::reset() { + GeographyObj::resetObject(); + clrObjFlagHidding(); + clrObjFlagCheckItemHitting(); + clrAllCheckKartHitFlag(); + mAnmObjMat.getFrameCtrl()->reset(); +} + +void TMapObjSun::createModel(JKRSolidHeap *heap, u32 p2) { + mModel.createDifferedModel(heap, p2, 0x200, 0); + mAnmObjMat.setExModel(&mModel); + mAnmObjMat.setAnmBase(sSunBtkAnm); + mAnmObjMat.initFrameCtrl(mAnmObjMat.mAnmBase); +} + +void TMapObjSun::loadAnimation() { + J3DModelData *modelData = mModel.getModelData(); + J3DAnmObjMaterial::setupTexSRTAnmData(&sSunBtkAnm, modelData, ObjUtility::getPtrCourseArc("/Objects/sun.btk")); +} + +void TMapObjSun::calc() { + mAnmObjMat.update(); +} + +void TMapObjSun::update() { + mAnmObjMat.anmFrameProc(); + GeographyObj::update(); +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 998889715264a2e3ad459fd08d671cf5c00871d3 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 19:04:13 +1000 Subject: [PATCH 27/29] GeoObjMgr - Implement TMapObjBubble. --- include/Shiraiwa/Objects/MapObjBubble.h | 52 ++++++ src/Sato/GeographyObjMgr.cpp | 3 +- src/Shiraiwa/MapObjBubble.cpp | 230 ++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 include/Shiraiwa/Objects/MapObjBubble.h diff --git a/include/Shiraiwa/Objects/MapObjBubble.h b/include/Shiraiwa/Objects/MapObjBubble.h new file mode 100644 index 00000000..0a880315 --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjBubble.h @@ -0,0 +1,52 @@ +#ifndef MAPOBJBUBBLE_H +#define MAPOBJBUBBLE_H + +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/Objects/MapObjHioNode.h" + +class TMapObjBubble : public TMapObjHioNode, public StateObserver { +public: + TMapObjBubble(const CrsData::SObject &); // 0x802b9e5c + virtual ~TMapObjBubble(); // 0x802b9f00 + virtual void createColModel(J3DModelData *); // 0x802b9fe4 + virtual const char *getBmdFileName(); // 0x802ba010 + virtual void createModel(JKRSolidHeap *, u32); // 0x802ba038 + virtual void loadAnimation(); // 0x802ba098 + virtual void update(); // 0x802ba1b8 + virtual void reset(); // 0x802ba1fc + virtual void calc(); // 0x802ba438 + void initFunc_Start(); // 0x802ba470 + void stopParticle(); // 0x802ba490 + void doFunc_Start(); // 0x802ba4ac + void initFunc_Dive(); // 0x802ba4e4 + void doFunc_Dive(); // 0x802ba500 + void initFunc_Symptom(); // 0x802ba538 + void doFunc_Symptom(); // 0x802ba53c + void initFunc_Jump(); // 0x802ba574 + void doFunc_Jump(); // 0x802ba62c + static StateFuncSet sTable[4]; // 0x803a7c00 + static f32 sGravity; // 0x80415330 + static J3DAnmTextureSRTKey *sBubbleBtkAnm; // 0x80417008 + + // Inline/Unused + //void startParticle(); + //void moveEmitter(); + + // Inline + virtual void MoveExec(); // 0x802ba14c + virtual void InitExec(); // 0x802ba0e0 + + + J3DAnmObjMaterial mAnmObjMat; + JGeometry::TVec3f _178; + u16 mCountStateStart; + u16 mCountStateDive; + u16 mCountStateSymptom; + f32 _18c; + f32 _190; + f32 _194; + JPABaseEmitter *mEmitter; +}; // class MapObjBubble +#endif // MAPOBJBUBBLE_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index f18bd6dc..37ed4efa 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -41,6 +41,7 @@ #include "Shiraiwa/LensFlare.h" //#include "Shiraiwa/MapObjPoihana.h" #include "Shiraiwa/Objects/MapObjAward.h" +#include "Shiraiwa/Objects/MapObjBubble.h" #include "Shiraiwa/Objects/MapObjDonkyRock.h" #include "Shiraiwa/Objects/MapObjDonkyRockGen.h" #include "Shiraiwa/Objects/MapObjDonkyTree.h" @@ -146,7 +147,7 @@ GEO_OBJ_NEW(TMapObjIceBlock); GEO_OBJ_NEW(TMapObjNoMove); GEO_OBJ_NEW(GeoKuribo); GEO_OBJ_NEW(TMapObjSun); -// GEO_OBJ_NEW(TMapObjBubble); +GEO_OBJ_NEW(TMapObjBubble); // GEO_OBJ_NEW(TMapObjDesun); // GEO_OBJ_NEW(TMapObjSandPillar); // GEO_OBJ_NEW(TMapObjFerriswheel); diff --git a/src/Shiraiwa/MapObjBubble.cpp b/src/Shiraiwa/MapObjBubble.cpp index e69de29b..915e0ddb 100644 --- a/src/Shiraiwa/MapObjBubble.cpp +++ b/src/Shiraiwa/MapObjBubble.cpp @@ -0,0 +1,230 @@ +#include "Shiraiwa/Objects/MapObjBubble.h" +#include "Inagaki/GameSoundMgr.h" +#include "JSystem/JGeometry/Matrix.h" +#include "JSystem/JGeometry/Vec.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kaneshige/RaceMgr.h" +#include "Sato/GeographyObj.h" +#include "Sato/JPEffectMgr.h" +#include "Sato/ObjUtility.h" +#include "Sato/StateObserver.h" +#include "Shiraiwa/SiUtil.h" +#include "dolphin/mtx.h" + +StateObserver::StateFuncSet TMapObjBubble::sTable[4] = { + { 0, &TMapObjBubble::initFunc_Start, &TMapObjBubble::doFunc_Start }, + { 1, &TMapObjBubble::initFunc_Dive, &TMapObjBubble::doFunc_Dive }, + { 2, &TMapObjBubble::initFunc_Symptom, &TMapObjBubble::doFunc_Symptom }, + { 3, &TMapObjBubble::initFunc_Jump, &TMapObjBubble::doFunc_Jump }, +}; + +f32 TMapObjBubble::sGravity = 1.0f; +J3DAnmTextureSRTKey *TMapObjBubble::sBubbleBtkAnm; + +TMapObjBubble::TMapObjBubble(const CrsData::SObject &sObject) : TMapObjHioNode(sObject) { + createSoundMgr(); +} + +TMapObjBubble::~TMapObjBubble() {} + +void TMapObjBubble::createColModel(J3DModelData *modelData) { + createBoundsSphere(modelData); +} + +const char *TMapObjBubble::getBmdFileName() { + static const char *cBmdName = "/Objects/Bubble1.bmd"; + return cBmdName; +} + +void TMapObjBubble::createModel(JKRSolidHeap *heap, u32 p2) { + mModel.createDifferedModel(heap, p2, 0x200, 0); + mAnmObjMat.setExModel(&mModel); + mAnmObjMat.setAnmBase(sBubbleBtkAnm); + mAnmObjMat.initFrameCtrl(mAnmObjMat.mAnmBase); +} + +void TMapObjBubble::loadAnimation() { + J3DModelData *modelData = mModel.getModelData(); + J3DAnmObjMaterial::setupTexSRTAnmData(&sBubbleBtkAnm, modelData, ObjUtility::getPtrCourseArc("/Objects/Bubble1.btk")); +} + +void TMapObjBubble::InitExec() { Observer_FindAndInit(TMapObjBubble, 4); } + +void TMapObjBubble::MoveExec() { Observer_FindAndExec(TMapObjBubble, 4); } + +void TMapObjBubble::update() { + mAnmObjMat.anmFrameProc(); + GeographyObj::update(); +} + +void TMapObjBubble::reset() { + stRandom *stRndm; + + GeographyObj::resetObject(); + ResetState(); + mCountStateDive = mObjData->mParam1; + if (mCountStateDive == 0) { + mCountStateDive = 0xb4; + } + mCountStateStart = mObjData->mParam2; + mCountStateSymptom = mObjData->mParam3; + if (mCountStateSymptom == 0) { + mCountStateSymptom = 0x3c; + } + + // Why is this cast to a u32 when this is a float? + _18c = (u32)(mObjData->mParam4 * 0.01f); + if (_18c == 0.0f) { + _18c = 80.0f; + } + + _190 = mObjData->mParam5 * 0.01f; + mAnmObjMat.resetFrame(); + SiUtil::setRandomStartFrame(mAnmObjMat.getFrameCtrl(), GeographyObj::getGeoRnd()); + clrObjFlagHidding(); + setAllCheckKartHitFlag(); + _58 = 0xd; + mRotMtx.getXDir(_178); + _178.normalize(); + mEmitter = nullptr; + _194 = 0.0f; +} + +void TMapObjBubble::calc() { + ExecuteState(); + mAnmObjMat.update(); +} + +void TMapObjBubble::initFunc_Start() { + stopParticle(); +} + +void TMapObjBubble::stopParticle() { + if (mEmitter == nullptr) { + return; + } + mEmitter->setFlag(1); +} + +void TMapObjBubble::doFunc_Start() { + if (getStateCount() > mCountStateStart) { + setState(2); + } +} + +void TMapObjBubble::initFunc_Dive() { + if (mEmitter == nullptr) { + return; + } + mEmitter->setFlag(1); +} + +void TMapObjBubble::doFunc_Dive() { + if (getStateCount() > mCountStateDive) { + setState(2); + } +} + +void TMapObjBubble::initFunc_Symptom() {} + +void TMapObjBubble::doFunc_Symptom() { + if (getStateCount() > mCountStateSymptom) { + setState(3); + } +} + +void TMapObjBubble::initFunc_Jump() { + mVel.set(0.0f, _18c, 0.0f); + if (mEmitter == nullptr) { + mEmitter = JPEffectMgr::getEffectMgr()->createEmt("mk_bubble_a", mPos); + #line 199 + JUT_ASSERT(mEmitter != 0); + } + if (mEmitter != nullptr) { + mEmitter->clearStatus(1); + } +} + +void TMapObjBubble::doFunc_Jump() { + JGeometry::TPos3f local_118; + JGeometry::TVec3f local_114; + JGeometry::TVec3f local_124; + JGeometry::TVec3f local_130; + JGeometry::TVec3f local_13c; + JGeometry::TVec3f local_148; + + mVel.y -= sGravity; + + local_124.set(_178); + local_124.normalize(); + local_124.scale(_190); + + mVel.add(local_124); + mPos.add(mVel); + + if (mPos.y < mObjData->position.y) { + mPos.set(mObjData->position); + setState(1); + } + + local_13c.set(mVel); + local_13c.normalize(); + + local_148.set(mObjData->zNorm); + local_148.normalize(); + + local_130.cross(local_13c, local_148); + local_130.normalize(); + + local_148.cross(local_130, local_13c); + local_148.normalize(); + + mRotMtx.setXYZDir(local_130, local_13c, local_148); + + CrsGround CStack_e8(RCMGetCourse()); + CStack_e8.search(mPos); + + f32 dVar7 = mPos.y - CStack_e8.getSplashHeight(); + if (dVar7 * _194 < 0.0f) { + JPEffectMgr::getEffectMgr()->createEmt("mk_bubbleLand_a", mPos)->setGlobalScale(mScale); + JPEffectMgr::getEffectMgr()->createEmt("mk_bubbleLand_b", mPos)->setGlobalScale(mScale); + + if (mVel.y > 0.0f) { + getSoundMgr()->setSe(0x4003b); + } else { + getSoundMgr()->setSe(0x4003c); + } + } + _194 = dVar7; + + PSMTXIdentity(local_118); + + // Not sure why scale needs to be copied here...? + JGeometry::TVec3f scale; + scale.set(mScale.x, mScale.y, mScale.z); + + local_118[0][0] = scale.x; + local_118[0][1] = 0.0f; + local_118[0][2] = 0.0f; + + local_118[1][0] = 0.0f; + local_118[1][1] = scale.y; + local_118[1][2] = 0.0f; + + local_118[2][0] = 0.0f; + local_118[2][1] = 0.0f; + local_118[2][2] = scale.z; + + PSMTXConcat(local_118, mRotMtx, local_118); + local_118[0][3] = mPos.x; + local_118[1][3] = mPos.y; + local_118[2][3] = mPos.z; + JPABaseEmitter *emt = mEmitter; + if (emt != nullptr) { + JPASetRMtxSTVecfromMtx(local_118, emt->mGlobalRot, &emt->mGlobalScl, &emt->mGlobalTrs); + emt->setGlobalParticleScale(emt->mGlobalScl); + } +} + +#include "JSystem/JAudio/JASFakeMatch2.h" From 46027b5ad262b3cb0b703557ea8335da5b83097f Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 19:16:42 +1000 Subject: [PATCH 28/29] Set proper Update JPEffectMgr::createEmtCameraClip() function signature to have return type of `JPABaseEmitter *`. This is used by MapObjFireObj in the `TMapObjKpFireBarBall::calc()` function. --- include/Sato/JPEffectMgr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Sato/JPEffectMgr.h b/include/Sato/JPEffectMgr.h index ab0cde74..4efe41b8 100644 --- a/include/Sato/JPEffectMgr.h +++ b/include/Sato/JPEffectMgr.h @@ -16,7 +16,7 @@ class JPEffectMgr void create_forMenu(); // 0x8023038c JPABaseEmitter *createEmt(u16, const JGeometry::TVec3f &); // 0x8023050c JPABaseEmitter *createEmt(const char *, const JGeometry::TVec3f &); // 0x80230544 - void createEmtCameraClip(const char *, const JGeometry::TVec3f &); // 0x80230590 + JPABaseEmitter *createEmtCameraClip(const char *, const JGeometry::TVec3f &); // 0x80230590 JPABaseEmitter *createEmt2D(const char *, const JGeometry::TVec3f &); // 0x80230600 JPABaseEmitter *createEmt(const char *, const JGeometry::TVec3f &, Mtx); // 0x8023064c void createEmtThunder(const char *, const JGeometry::TVec3f &); // 0x802306c0 From 4a3e5b16ff30184e52388c731b65d31e05f8ace2 Mon Sep 17 00:00:00 2001 From: MJ Date: Thu, 23 Jul 2026 19:19:09 +1000 Subject: [PATCH 29/29] GeoObjMgr - Implement TMapObjPeachTree. --- include/Shiraiwa/Objects/MapObjPeachTree.h | 34 ++++++++++++ src/Sato/GeographyObjMgr.cpp | 5 +- src/Shiraiwa/MapObjPeachTree.cpp | 61 ++++++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 include/Shiraiwa/Objects/MapObjPeachTree.h diff --git a/include/Shiraiwa/Objects/MapObjPeachTree.h b/include/Shiraiwa/Objects/MapObjPeachTree.h new file mode 100644 index 00000000..090a7d9e --- /dev/null +++ b/include/Shiraiwa/Objects/MapObjPeachTree.h @@ -0,0 +1,34 @@ +#ifndef MAPOBJPEACHTREE_H +#define MAPOBJPEACHTREE_H + +#include "Sato/Objects/GeoTree.h" + + +class TMapObjPeachTree : public GeoMarioTree1 { +public: + TMapObjPeachTree(const CrsData::SObject&); + virtual ~TMapObjPeachTree(); + + virtual const char* getBmdFileName(); + virtual void createColModel(J3DModelData*); + virtual GeoAnmTableEntry *getAnmTbl(); + virtual u16 getSizeAnmTbl(); + + static GeoAnmTableEntry sBckAnmTable; +}; + +class TMapObjPeachTree2 : public GeoMarioTree1 { +public: + + TMapObjPeachTree2(const CrsData::SObject&); + virtual ~TMapObjPeachTree2(); + + virtual const char* getBmdFileName(); + virtual void createColModel(J3DModelData*); + virtual GeoAnmTableEntry *getAnmTbl(); + virtual u16 getSizeAnmTbl(); + + static GeoAnmTableEntry sBckAnmTable; +}; + +#endif // MAPOBJPEACHTREE_H diff --git a/src/Sato/GeographyObjMgr.cpp b/src/Sato/GeographyObjMgr.cpp index 37ed4efa..0f4702cd 100644 --- a/src/Sato/GeographyObjMgr.cpp +++ b/src/Sato/GeographyObjMgr.cpp @@ -51,6 +51,7 @@ #include "Shiraiwa/Objects/MapObjHeyho.h" #include "Shiraiwa/Objects/MapObjIceBlock.h" #include "Shiraiwa/Objects/MapObjNoMove.h" +#include "Shiraiwa/Objects/MapObjPeachTree.h" #include "Shiraiwa/Objects/MapObjPool.h" #include "Shiraiwa/Objects/MapObjSkyShip.h" #include "Shiraiwa/Objects/MapObjSnowMan.h" @@ -134,7 +135,7 @@ GEO_OBJ_NEW(TMapObjGeyser); GEO_OBJ_NEW(TMapObjGeyserSearch); GEO_OBJ_NEW_S(TTestStrBarrel); GEO_OBJ_NEW_S(TTestStrItem); -// GEO_OBJ_NEW(TMapObjPeachTree); +GEO_OBJ_NEW(TMapObjPeachTree); GEO_OBJ_NEW(TMapObjSnowRock); GEO_OBJ_NEW(TTestRollObj); GEO_OBJ_NEW(TMapObjFountain); @@ -194,7 +195,7 @@ GEO_OBJ_NEW(TMapObjDemoFountain); // GEO_OBJ_NEW(TMapObjKpFireBar); // GEO_OBJ_NEW(TMapObjSwimNossie); // GEO_OBJ_NEW(TMapObjPtera); -// GEO_OBJ_NEW(TMapObjPeachTree2); +GEO_OBJ_NEW(TMapObjPeachTree2); // GEO_OBJ_NEW(TMapObjYoshiHeli); GEO_OBJ_NEW(TMapObjDesertTree); GEO_OBJ_NEW(TMapObjWluSearchLight); diff --git a/src/Shiraiwa/MapObjPeachTree.cpp b/src/Shiraiwa/MapObjPeachTree.cpp index e69de29b..144aa5a1 100644 --- a/src/Shiraiwa/MapObjPeachTree.cpp +++ b/src/Shiraiwa/MapObjPeachTree.cpp @@ -0,0 +1,61 @@ +#include "Shiraiwa/Objects/MapObjPeachTree.h" +#include "Sato/GeographyObj.h" + +GeoAnmTableEntry TMapObjPeachTree::sBckAnmTable = { + 0, "PeachTree1_wait.bck" +}; + +TMapObjPeachTree::TMapObjPeachTree(const CrsData::SObject &sObject) : GeoMarioTree1(sObject) {} + +TMapObjPeachTree::~TMapObjPeachTree() {} + +const char *TMapObjPeachTree::getBmdFileName() { + static const char *cTreeBmdName = "PeachTree1.bmd"; + return cTreeBmdName; +} + +GeoAnmTableEntry *TMapObjPeachTree::getAnmTbl() { + if (availBckAnm()) { + return &sBckAnmTable; + } + return nullptr; +} + +void TMapObjPeachTree::createColModel(J3DModelData *modelData) { + createBoundsCylinder(modelData, 210.0f, 500.0f); +} + +u16 TMapObjPeachTree::getSizeAnmTbl() { + return 8; +} + +GeoAnmTableEntry TMapObjPeachTree2::sBckAnmTable = { + 0, "PeachTree2_wait.bck" +}; + +TMapObjPeachTree2::TMapObjPeachTree2(const CrsData::SObject &sObject) : GeoMarioTree1(sObject) {} + +TMapObjPeachTree2::~TMapObjPeachTree2() {} + +const char *TMapObjPeachTree2::getBmdFileName() { + static const char* cTreeBmdName = "PeachTree2.bmd"; + return cTreeBmdName; +} + +GeoAnmTableEntry *TMapObjPeachTree2::getAnmTbl() { + if (availBckAnm()) { + return &sBckAnmTable; + } + return nullptr; +} + +u16 TMapObjPeachTree2::getSizeAnmTbl() { + return 8; +} + +void TMapObjPeachTree2::createColModel(J3DModelData *modelData) { + createBoundsCylinder(modelData, 110.0f, 500.0f); +} + + +#include "JSystem/JAudio/JASFakeMatch2.h"