diff --git a/data/file_list.yml b/data/file_list.yml index e31c0742..988def97 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -264305,60 +264305,60 @@ Library/Movement/ClockMovement.o: label: - _ZN2al13ClockMovementC1ERKNS_13ActorInitInfoE - _ZN2al13ClockMovementC2ERKNS_13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x952a1c size: 100 label: _ZN2al13ClockMovement8exeDelayEv - status: NotDecompiled + status: Matching - offset: 0x952a80 size: 204 label: _ZN2al13ClockMovement13exeRotateSignEv - status: NotDecompiled + status: Matching - offset: 0x952b4c size: 156 label: _ZN2al13ClockMovement9exeRotateEv - status: NotDecompiled + status: Matching - offset: 0x952be8 size: 96 label: _ZN2al13ClockMovement7exeWaitEv - status: NotDecompiled + status: Matching - offset: 0x952c48 size: 64 label: _ZNK2al13ClockMovement16isFirstStepDelayEv - status: NotDecompiled + status: Matching - offset: 0x952c88 size: 68 label: _ZNK2al13ClockMovement21isFirstStepRotateSignEv - status: NotDecompiled + status: Matching - offset: 0x952ccc size: 68 label: _ZNK2al13ClockMovement17isFirstStepRotateEv - status: NotDecompiled + status: Matching - offset: 0x952d10 size: 64 label: _ZNK2al13ClockMovement15isFirstStepWaitEv - status: NotDecompiled + status: Matching - offset: 0x952d50 size: 36 label: _ZN2al13ClockMovementD0Ev - status: NotDecompiled + status: Matching lazy: true - offset: 0x952d74 size: 104 - label: '' - status: NotDecompiled + label: _ZNK12_GLOBAL__N_121ClockMovementNrvDelay7executeEPN2al11NerveKeeperE + status: Matching - offset: 0x952ddc size: 8 - label: '' - status: NotDecompiled + label: _ZNK12_GLOBAL__N_126ClockMovementNrvRotateSign7executeEPN2al11NerveKeeperE + status: Matching - offset: 0x952de4 size: 8 - label: '' - status: NotDecompiled + label: _ZNK12_GLOBAL__N_122ClockMovementNrvRotate7executeEPN2al11NerveKeeperE + status: Matching - offset: 0x952dec size: 100 - label: '' - status: NotDecompiled + label: _ZNK12_GLOBAL__N_120ClockMovementNrvWait7executeEPN2al11NerveKeeperE + status: Matching Library/Movement/EnemyStateBlowDown.o: '.text': - offset: 0x952e50 diff --git a/lib/al/Library/MapObj/ClockMapParts.cpp b/lib/al/Library/MapObj/ClockMapParts.cpp index 1c810706..d7badee0 100644 --- a/lib/al/Library/MapObj/ClockMapParts.cpp +++ b/lib/al/Library/MapObj/ClockMapParts.cpp @@ -250,7 +250,7 @@ void ClockMapParts::exeRotate() { mTimer++; if (mTimer >= mRotateTimer) { - mCurrentStep = modi(mCurrentStep + mTurnStepCount + 1, mTurnStepCount); + mCurrentStep = wrapValue(mCurrentStep + 1, mTurnStepCount); startNerveAction(this, "Wait"); tryStartSe(this, "RotateEnd"); } diff --git a/lib/al/Library/Math/MathUtil.h b/lib/al/Library/Math/MathUtil.h index ed892961..140af19b 100644 --- a/lib/al/Library/Math/MathUtil.h +++ b/lib/al/Library/Math/MathUtil.h @@ -205,6 +205,10 @@ void makeBoxMullerRandomGauss(sead::Vector2f* outBox, f32 randA, f32 randB); f32 modf(f32 a, f32 b); s32 modi(s32 a, s32 b); +inline s32 wrapValue(s32 value, s32 maxRange) { + return modi(value + maxRange, maxRange); +} + inline f32 wrapValue(f32 value, f32 maxRange) { return modf(value + maxRange, maxRange) + 0.0f; } diff --git a/lib/al/Library/Movement/ClockMovement.cpp b/lib/al/Library/Movement/ClockMovement.cpp new file mode 100644 index 00000000..8c3dada2 --- /dev/null +++ b/lib/al/Library/Movement/ClockMovement.cpp @@ -0,0 +1,101 @@ +#include "Library/Movement/ClockMovement.h" + +#include "Library/Math/MathUtil.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" +#include "Library/Placement/PlacementFunction.h" + +namespace { +using namespace al; + +NERVE_IMPL(ClockMovement, Delay); +NERVE_IMPL(ClockMovement, RotateSign); +NERVE_IMPL(ClockMovement, Rotate); +NERVE_IMPL(ClockMovement, Wait); + +NERVES_MAKE_STRUCT(ClockMovement, Delay, RotateSign, Rotate); +NERVES_MAKE_NOSTRUCT(ClockMovement, Wait); +} // namespace + +namespace al { + +ClockMovement::ClockMovement(const ActorInitInfo& info) : NerveExecutor("クロックパーツ動作") { + getQuat(&mInitialQuat, info); + mCurrentQuat = mInitialQuat; + tryGetArg(&mClockAngleDegree, info, "ClockAngleDegree"); + tryGetArg(&mRotateAxis, info, "RotateAxis"); + tryGetArg(&mDelayTime, info, "DelayTime"); + tryGetArg(&mRotateSignTime, info, "RotateSignTime"); + tryGetArg(&mRotateTime, info, "RotateTime"); + tryGetArg(&mWaitTime, info, "WaitTime"); + + if (mDelayTime == 0) + initNerve(&NrvClockMovement.RotateSign, 0); + else + initNerve(&NrvClockMovement.Delay, 0); + + s32 stepsPerCycle = 1; + if (mClockAngleDegree != 0) { + stepsPerCycle = sead::Mathi::lcm(sead::Mathi::abs(mClockAngleDegree), 360) / + sead::Mathi::abs(mClockAngleDegree); + } + mMaxStepIndex = stepsPerCycle; +} + +void ClockMovement::exeDelay() { + if (isGreaterEqualStep(this, mDelayTime - 1)) { + if (mRotateSignTime > 0) + setNerve(this, &NrvClockMovement.RotateSign); + else + setNerve(this, &NrvClockMovement.Rotate); + } +} + +void ClockMovement::exeRotateSign() { + f32 rotateAngle = wrapValue(static_cast(mCurrentStepIndex * mClockAngleDegree), 360.0f); + + rotateQuatLocalDirDegree(&mCurrentQuat, mInitialQuat, mRotateAxis, + rotateAngle + + sead::Mathf::sin(getNerveStep(this) * sead::Mathf::pi2() / 18.0f)); + + if (isGreaterEqualStep(this, mRotateSignTime - 1)) + setNerve(this, &NrvClockMovement.Rotate); +} + +void ClockMovement::exeRotate() { + f32 rotateAngle = wrapValue( + (calcNerveRate(this, mRotateTime) + mCurrentStepIndex) * mClockAngleDegree, 360.0f); + rotateQuatLocalDirDegree(&mCurrentQuat, mInitialQuat, mRotateAxis, rotateAngle); + + if (isGreaterEqualStep(this, mRotateTime)) { + mCurrentStepIndex = wrapValue(mCurrentStepIndex + 1, mMaxStepIndex); + setNerve(this, &Wait); + } +} + +void ClockMovement::exeWait() { + if (isGreaterEqualStep(this, mWaitTime)) { + if (mRotateSignTime > 0) + setNerve(this, &NrvClockMovement.RotateSign); + else + setNerve(this, &NrvClockMovement.Rotate); + } +} + +bool ClockMovement::isFirstStepDelay() const { + return isNerve(this, &NrvClockMovement.Delay) && isFirstStep(this); +} + +bool ClockMovement::isFirstStepRotateSign() const { + return isNerve(this, &NrvClockMovement.RotateSign) && isFirstStep(this); +} + +bool ClockMovement::isFirstStepRotate() const { + return isNerve(this, &NrvClockMovement.Rotate) && isFirstStep(this); +} + +bool ClockMovement::isFirstStepWait() const { + return isNerve(this, &Wait) && isFirstStep(this); +} + +} // namespace al diff --git a/lib/al/Library/Movement/ClockMovement.h b/lib/al/Library/Movement/ClockMovement.h new file mode 100644 index 00000000..72129303 --- /dev/null +++ b/lib/al/Library/Movement/ClockMovement.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include "Library/Nerve/NerveExecutor.h" + +namespace al { +struct ActorInitInfo; + +class ClockMovement : public NerveExecutor { +public: + ClockMovement(const ActorInitInfo& info); + void exeDelay(); + void exeRotateSign(); + void exeRotate(); + void exeWait(); + bool isFirstStepDelay() const; + bool isFirstStepRotateSign() const; + bool isFirstStepRotate() const; + bool isFirstStepWait() const; + +private: + sead::Quatf mCurrentQuat = sead::Quatf::unit; + sead::Quatf mInitialQuat = sead::Quatf::unit; + s32 mRotateAxis = 0; + s32 mClockAngleDegree = 90; + s32 mCurrentStepIndex = 0; + s32 mMaxStepIndex = 4; + s32 mDelayTime = 0; + s32 mRotateSignTime = 36; + s32 mRotateTime = 60; + s32 mWaitTime = 0; +}; + +static_assert(sizeof(ClockMovement) == 0x50); +} // namespace al diff --git a/lib/al/Library/Movement/SwingMovement.cpp b/lib/al/Library/Movement/SwingMovement.cpp index 9366d4a0..4ef09bf4 100644 --- a/lib/al/Library/Movement/SwingMovement.cpp +++ b/lib/al/Library/Movement/SwingMovement.cpp @@ -59,7 +59,7 @@ void SwingMovement::exeMove() { if (updateRotate()) setNerve(this, &Stop); - mFrameInCycle = modi((mFrameInCycle + 1) + mSwingCycle, mSwingCycle); + mFrameInCycle = wrapValue(mFrameInCycle + 1, mSwingCycle); } void SwingMovement::exeStop() { diff --git a/lib/al/Library/Rail/RailUtil.cpp b/lib/al/Library/Rail/RailUtil.cpp index 1f3160ff..a1158453 100644 --- a/lib/al/Library/Rail/RailUtil.cpp +++ b/lib/al/Library/Rail/RailUtil.cpp @@ -323,11 +323,8 @@ s32 getNextRailPointNo(const IUseRail* railHolder) { s32 newIndex = getRailPointNo(railHolder) + modifier; s32 railPointNum = getRailPointNum(railHolder); - if (isLoop) { - s32 sum = railPointNum + newIndex; - s32 railPointNumAgain = getRailPointNum(railHolder); - return modi(sum + railPointNumAgain, railPointNumAgain); - } + if (isLoop) + return wrapValue(railPointNum + newIndex, getRailPointNum(railHolder)); return sead::Mathi::clamp2(0, newIndex, railPointNum - 1); } diff --git a/lib/al/Project/Fluid/FlowMapCtrl.cpp b/lib/al/Project/Fluid/FlowMapCtrl.cpp index 0a4220c2..22ca8155 100644 --- a/lib/al/Project/Fluid/FlowMapCtrl.cpp +++ b/lib/al/Project/Fluid/FlowMapCtrl.cpp @@ -17,8 +17,7 @@ void FlowMapCtrl::update() { flowParameters.y = calcRate01(halfInterval - sead::Mathi::abs(halfInterval - mFlowStep), 0.0f, halfInterval); flowParameters.z = calcRate01(mFlowStep, 0.0f, mInterval); - flowParameters.w = - calcRate01(modi(mFlowStep + halfInterval + mInterval, mInterval), 0.0f, mInterval); + flowParameters.w = calcRate01(wrapValue(mFlowStep + halfInterval, mInterval), 0.0f, mInterval); s32 materialCount = getMaterialCount(mParent); for (s32 i = 0; i < materialCount; i++) { @@ -27,7 +26,7 @@ void FlowMapCtrl::update() { } mFlowStep++; - mFlowStep = modi(mFlowStep + mInterval, mInterval); + mFlowStep = wrapValue(mFlowStep, mInterval); } } // namespace al diff --git a/src/Boss/Koopa/KoopaLandPointHolder.cpp b/src/Boss/Koopa/KoopaLandPointHolder.cpp index aa15a06d..40b0c110 100644 --- a/src/Boss/Koopa/KoopaLandPointHolder.cpp +++ b/src/Boss/Koopa/KoopaLandPointHolder.cpp @@ -65,8 +65,8 @@ void KoopaLandPointHolder::decidePointEitherFarSide(const sead::Vector3f& pos) { } mInvalidPoints[mCurrentLandPoint] = false; - s32 prevPoint = al::modi(mCurrentLandPoint - 1 + mLandPoints, mLandPoints); - s32 nextPoint = al::modi(mCurrentLandPoint + 1 + mLandPoints, mLandPoints); + s32 prevPoint = al::wrapValue(mCurrentLandPoint - 1, mLandPoints); + s32 nextPoint = al::wrapValue(mCurrentLandPoint + 1, mLandPoints); f32 prevDist = getKoopaLandPointDistance(mPointsTrans[prevPoint], pos); f32 nextDist = getKoopaLandPointDistance(mPointsTrans[nextPoint], pos); diff --git a/src/Enemy/Bubble.cpp b/src/Enemy/Bubble.cpp index 549fd596..69ef1172 100644 --- a/src/Enemy/Bubble.cpp +++ b/src/Enemy/Bubble.cpp @@ -638,7 +638,8 @@ void Bubble::control() { if (!al::isNerve(this, &NrvBubble.StandBy) && !al::isNerve(this, &NrvBubble.Delay) && (!isHack() || !rs::isActiveHackStartDemo(mPlayerHack)) && !al::isClipped(mClippingProbeActor) && !mIsClipped) { - mReviveDelayCount = al::modi(mReviveDelayCount + 1 + mReviveDelayTime, mReviveDelayTime); + mReviveDelayCount = + al::wrapValue(static_cast(mReviveDelayCount + 1), mReviveDelayTime); } mIsClipped = al::isClipped(mClippingProbeActor); diff --git a/src/Enemy/Gamane.cpp b/src/Enemy/Gamane.cpp index bb806c8e..5250221e 100644 --- a/src/Enemy/Gamane.cpp +++ b/src/Enemy/Gamane.cpp @@ -505,7 +505,8 @@ void Gamane::exeHack() { mCoinsLeft--; } - mHackCoinAppearCounter = al::modi((mHackCoinAppearCounter++ + 1) + 6, 6); + // NOTE: this is only one increment, as post-incrementing is used + mHackCoinAppearCounter = al::wrapValue(mHackCoinAppearCounter++ + 1, 6); } void Gamane::exeTrampled() { diff --git a/src/Enemy/HosuiTrailKeeper.cpp b/src/Enemy/HosuiTrailKeeper.cpp index 05199e01..a0a63a76 100644 --- a/src/Enemy/HosuiTrailKeeper.cpp +++ b/src/Enemy/HosuiTrailKeeper.cpp @@ -25,7 +25,7 @@ HosuiTrailKeeper::HosuiTrailKeeper(const al::ActorInitInfo& initInfo) { void HosuiTrailKeeper::appearTrail(const sead::Vector3f& pos, const sead::Vector3f& dir) { s32 count = mTrails.size(); - s32 prevIdx = al::modi(mIndex + count - 1 + count, count); + s32 prevIdx = al::wrapValue(mIndex + count - 1, count); HosuiTrail* prevTrail = mTrails[prevIdx]; if (al::isAlive(prevTrail) && (pos - al::getTrans(prevTrail)).length() < 120.0f) @@ -56,12 +56,12 @@ void HosuiTrailKeeper::appearTrail(const sead::Vector3f& pos, const sead::Vector trail->setFollowCollisionParts(triangle.getCollisionParts()); } - s32 disappearIdx = al::modi(mIndex + 5 + count, count); + s32 disappearIdx = al::wrapValue(mIndex + 5, count); HosuiTrail* disappearTrail = mTrails[disappearIdx]; if (al::isAlive(disappearTrail)) disappearTrail->disappear(); - mIndex = al::modi(mIndex + 1 + count, count); + mIndex = al::wrapValue(mIndex + 1, count); } void HosuiTrailKeeper::forceKillAll() { diff --git a/src/Layout/MenuSelectParts.cpp b/src/Layout/MenuSelectParts.cpp index 8bcc7033..e39284eb 100644 --- a/src/Layout/MenuSelectParts.cpp +++ b/src/Layout/MenuSelectParts.cpp @@ -243,8 +243,7 @@ void MenuSelectParts::exeSelect() { s32 direction = mKeyRepeatCtrl->isUp() ? -1 : 1; al::startAction(mLayoutArray[calcPartsIndex(mCursorItemIndex)], "Wait"); - mCursorItemIndex = - al::modi(mCursorItemIndex + direction + mMenuItemAmount, mMenuItemAmount); + mCursorItemIndex = al::wrapValue(mCursorItemIndex + direction, mMenuItemAmount); f32 pitch = ((1.0f - (f32)mCursorItemIndex / (mMenuItemAmount - 1)) * 0.375f) + 1.0f; al::PadRumbleParam param; diff --git a/src/Layout/WindowConfirmData.cpp b/src/Layout/WindowConfirmData.cpp index 4fc4af7c..c84ea61a 100644 --- a/src/Layout/WindowConfirmData.cpp +++ b/src/Layout/WindowConfirmData.cpp @@ -161,15 +161,15 @@ void WindowConfirmData::exeWait() { if (rs::isRepeatUiDown(mWindowConfirmLayout)) { if (mSelectionCooldown == 0) - changeSelectingIdx(al::modi((mSelectionIndex + 1) + 2, 2)); - mSelectionCooldown = al::modi((mSelectionCooldown + 1) + 10, 10); + changeSelectingIdx(al::wrapValue(mSelectionIndex + 1, 2)); + mSelectionCooldown = al::wrapValue(mSelectionCooldown + 1, 10); return; } if (rs::isRepeatUiUp(mWindowConfirmLayout)) { if (mSelectionCooldown == 0) - changeSelectingIdx(al::modi((mSelectionIndex - 1) + 2, 2)); - mSelectionCooldown = al::modi((mSelectionCooldown + 1) + 10, 10); + changeSelectingIdx(al::wrapValue(mSelectionIndex - 1, 2)); + mSelectionCooldown = al::wrapValue(mSelectionCooldown + 1, 10); return; } diff --git a/src/Npc/SmallBirdStateFlyAway.cpp b/src/Npc/SmallBirdStateFlyAway.cpp index 64b5cdca..936abdd9 100644 --- a/src/Npc/SmallBirdStateFlyAway.cpp +++ b/src/Npc/SmallBirdStateFlyAway.cpp @@ -82,18 +82,18 @@ void SmallBirdStateFlyAway::exeFlyAway() { mIsColliding = false; startActionAtRandomFrameIfNotPlaying(mActor, "Fly"); if (rs::isModeE3MovieRom()) { - gVerticalAccelIndex = al::modi(gVerticalAccelIndex + 7, 6); + gVerticalAccelIndex = al::wrapValue(gVerticalAccelIndex + 1, 6); mVerticalAccel = gE3MovieVerticalAccel[gVerticalAccelIndex]; - gHorizontalAccelIndex = al::modi(gHorizontalAccelIndex + 5, 4); + gHorizontalAccelIndex = al::wrapValue(gHorizontalAccelIndex + 1, 4); mHorizontalAccel = gE3MovieHorizontalAccel[gHorizontalAccelIndex]; } else { - gVerticalAccelIndex = al::modi(gVerticalAccelIndex + 5, 4); + gVerticalAccelIndex = al::wrapValue(gVerticalAccelIndex + 1, 4); mVerticalAccel = gVerticalAccel[gVerticalAccelIndex]; mHorizontalAccel = gHorizontalAccel; } mTargetAccelDir = {0, mVerticalAccel, mHorizontalAccel}; al::normalize(&mTargetAccelDir); - gCollisionCheckOffsetStep = al::modi(gCollisionCheckOffsetStep + 11, 10); + gCollisionCheckOffsetStep = al::wrapValue(gCollisionCheckOffsetStep + 1, 10); mCollisionCheckOffsetStep = gCollisionCheckOffsetStep; }