From bc392ae1087f6cba58d090020ec1b67ca1ce670b Mon Sep 17 00:00:00 2001 From: Narr the Reg <5944268+german77@users.noreply.github.com> Date: Sun, 12 Apr 2026 12:41:33 -0600 Subject: [PATCH] Boss/Koopa: Implement `KoopaLandPointHolder` (#1010) --- data/file_list.yml | 14 +-- src/Boss/Koopa/KoopaLandPointHolder.cpp | 120 ++++++++++++++++++++++++ src/Boss/Koopa/KoopaLandPointHolder.h | 32 +++++++ 3 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 src/Boss/Koopa/KoopaLandPointHolder.cpp create mode 100644 src/Boss/Koopa/KoopaLandPointHolder.h diff --git a/data/file_list.yml b/data/file_list.yml index fca53e02..1a4e0f4d 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -17145,31 +17145,31 @@ Boss/Koopa/KoopaLandPointHolder.o: label: - _ZN20KoopaLandPointHolderC1ERKN2al13ActorInitInfoE - _ZN20KoopaLandPointHolderC2ERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x0956b8 size: 252 label: _ZN20KoopaLandPointHolder18decidePointFarFromERKN4sead7Vector3IfEE - status: NotDecompiled + status: Matching - offset: 0x0957b4 size: 32 label: _ZN20KoopaLandPointHolder15invalidatePointEi - status: NotDecompiled + status: Matching - offset: 0x0957d4 size: 452 label: _ZN20KoopaLandPointHolder24decidePointEitherFarSideERKN4sead7Vector3IfEE - status: NotDecompiled + status: Matching - offset: 0x095998 size: 252 label: _ZN20KoopaLandPointHolder19decidePointNearFromERKN4sead7Vector3IfEE - status: NotDecompiled + status: Matching - offset: 0x095a94 size: 44 label: _ZN20KoopaLandPointHolder5resetEv - status: NotDecompiled + status: Matching - offset: 0x095ac0 size: 264 label: _ZNK20KoopaLandPointHolder21findNearestPointTransERKN4sead7Vector3IfEE - status: NotDecompiled + status: Matching Boss/Koopa/KoopaLv1.o: '.text': - offset: 0x095bc8 diff --git a/src/Boss/Koopa/KoopaLandPointHolder.cpp b/src/Boss/Koopa/KoopaLandPointHolder.cpp new file mode 100644 index 00000000..aa15a06d --- /dev/null +++ b/src/Boss/Koopa/KoopaLandPointHolder.cpp @@ -0,0 +1,120 @@ +#include "Boss/Koopa/KoopaLandPointHolder.h" + +#include "Library/Math/MathUtil.h" +#include "Library/Placement/PlacementFunction.h" +#include "Library/Placement/PlacementInfo.h" + +KoopaLandPointHolder::KoopaLandPointHolder(const al::ActorInitInfo& initInfo) { + al::getTrans(&mTrans, initInfo); + al::getQuat(&mQuat, initInfo); + mLandPoints = al::calcLinkChildNum(initInfo, "LandPoint"); + + if (mLandPoints <= 0) + return; + + mPointsQuat = new sead::Quatf[mLandPoints]; + mPointsTrans = new sead::Vector3f[mLandPoints]; + mInvalidPoints = new bool[mLandPoints]; + + for (s32 i = 0; i < mLandPoints; i++) { + mInvalidPoints[i] = false; + + al::PlacementInfo placementInfo; + al::getLinksInfoByIndex(&placementInfo, initInfo, "LandPoint", i); + al::getQuat(&mPointsQuat[i], placementInfo); + al::getTrans(&mPointsTrans[i], placementInfo); + } +} + +inline f32 getKoopaLandPointDistance(const sead::Vector3f& posA, const sead::Vector3f& posB) { + sead::Vector3f distance = posA - posB; + return sead::Mathf::sqrt(distance.x * distance.x + distance.z * distance.z); +} + +void KoopaLandPointHolder::decidePointFarFrom(const sead::Vector3f& pos) { + s32 selectedPoint = -1; + f32 maxDistance = 0.0f; + + for (s32 i = 0; i < mLandPoints; i++) { + if (mInvalidPoints[i]) + continue; + + f32 dist = getKoopaLandPointDistance(mPointsTrans[i], pos); + + if (selectedPoint < 0 || maxDistance < dist) { + selectedPoint = i; + maxDistance = dist; + } + } + + invalidatePoint(selectedPoint); + mCurrentLandPoint = selectedPoint; +} + +void KoopaLandPointHolder::invalidatePoint(s32 index) { + mInvalidPoints[index] = true; + + if (mCurrentLandPoint > -1) + mInvalidPoints[mCurrentLandPoint] = false; +} + +void KoopaLandPointHolder::decidePointEitherFarSide(const sead::Vector3f& pos) { + if (mCurrentLandPoint < 0) { + decidePointFarFrom(pos); + return; + } + + mInvalidPoints[mCurrentLandPoint] = false; + s32 prevPoint = al::modi(mCurrentLandPoint - 1 + mLandPoints, mLandPoints); + s32 nextPoint = al::modi(mCurrentLandPoint + 1 + mLandPoints, mLandPoints); + + f32 prevDist = getKoopaLandPointDistance(mPointsTrans[prevPoint], pos); + f32 nextDist = getKoopaLandPointDistance(mPointsTrans[nextPoint], pos); + + if (prevDist < nextDist) + mCurrentLandPoint = nextPoint; + else + mCurrentLandPoint = prevPoint; +} + +void KoopaLandPointHolder::decidePointNearFrom(const sead::Vector3f& pos) { + s32 selectedPoint = -1; + f32 minDistance = 0.0f; + + for (s32 i = 0; i < mLandPoints; i++) { + if (mInvalidPoints[i]) + continue; + + f32 dist = getKoopaLandPointDistance(mPointsTrans[i], pos); + + if (selectedPoint < 0 || dist < minDistance) { + selectedPoint = i; + minDistance = dist; + } + } + + invalidatePoint(selectedPoint); + mCurrentLandPoint = selectedPoint; +} + +void KoopaLandPointHolder::reset() { + for (s32 i = 0; i < mLandPoints; i++) + mInvalidPoints[i] = false; +} + +// NOTE: does not care about `mInvalidPoints` +const sead::Vector3f& KoopaLandPointHolder::findNearestPointTrans(const sead::Vector3f& pos) const { + f32 minDistance = getKoopaLandPointDistance(mPointsTrans[0], pos); + s32 selectedPoint = 0; + + for (s32 i = 1; i < mLandPoints; i++) { + f32 dist = getKoopaLandPointDistance(mPointsTrans[i], pos); + + if (dist < minDistance) { + selectedPoint = i; + minDistance = dist; + } + } + + return mPointsTrans[selectedPoint]; +} diff --git a/src/Boss/Koopa/KoopaLandPointHolder.h b/src/Boss/Koopa/KoopaLandPointHolder.h new file mode 100644 index 00000000..1e1ee277 --- /dev/null +++ b/src/Boss/Koopa/KoopaLandPointHolder.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +namespace al { +struct ActorInitInfo; +} // namespace al + +class KoopaLandPointHolder { +public: + KoopaLandPointHolder(const al::ActorInitInfo& initInfo); + + void decidePointFarFrom(const sead::Vector3f& pos); + void invalidatePoint(s32 index); + void decidePointEitherFarSide(const sead::Vector3f& pos); + void decidePointNearFrom(const sead::Vector3f& pos); + void reset(); + const sead::Vector3f& findNearestPointTrans(const sead::Vector3f& pos) const; + +private: + sead::Vector3f mTrans = {0.0f, 0.0f, 0.0f}; + sead::Quatf mQuat = sead::Quatf::unit; + s32 mCurrentLandPoint = -1; + s32 mLandPoints = 0; + sead::Quatf* mPointsQuat = nullptr; + sead::Vector3f* mPointsTrans = nullptr; + bool* mInvalidPoints = nullptr; +}; + +static_assert(sizeof(KoopaLandPointHolder) == 0x40);