Area: Implement ExtForceArea (#931)

This commit is contained in:
guymakinggames 2026-02-28 17:33:00 +00:00 committed by GitHub
parent 2e9976f0d2
commit db7946ca75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 85 additions and 8 deletions

View file

@ -1025,19 +1025,19 @@ Area/ExtForceArea.o:
- offset: 0x00546c
size: 88
label: _ZN12ExtForceAreaC2EPKc
status: NotDecompiled
status: Matching
- offset: 0x0054c4
size: 100
label: _ZN12ExtForceAreaC1EPKc
status: NotDecompiled
status: Matching
- offset: 0x005528
size: 156
label: _ZN12ExtForceArea4initERKN2al12AreaInitInfoE
status: NotDecompiled
status: Matching
- offset: 0x0055c4
size: 640
label: _ZNK12ExtForceArea12calcExtForceEPN4sead7Vector3IfEERKS2_S5_S5_
status: NotDecompiled
status: Matching
Area/ForceRecoveryKidsArea.o:
'.text':
- offset: 0x005844

76
src/Area/ExtForceArea.cpp Normal file
View file

@ -0,0 +1,76 @@
#include "Area/ExtForceArea.h"
#include "Library/Area/AreaInitInfo.h"
#include "Library/Area/AreaObjUtil.h"
#include "Library/Base/StringUtil.h"
#include "Library/Math/MathUtil.h"
#include "Library/Placement/PlacementFunction.h"
ExtForceArea::ExtForceArea(const char* name) : al::AreaObj(name) {}
void ExtForceArea::init(const al::AreaInitInfo& info) {
al::AreaObj::init(info);
const char* forceType = "Normal";
if (!al::tryGetStringArg(&forceType, static_cast<const al::PlacementInfo&>(info), "ForceType"))
return;
if (al::isEqualString(forceType, "Normal")) {
mSpeedVStep = 2.0f;
mSpeedVTarget = -40.0f;
mForceH = 0.98f;
} else if (al::isEqualString(forceType, "Weak")) {
mSpeedVStep = 0.25f;
mSpeedVTarget = -40.0f;
mForceH = 0.98f;
}
}
void ExtForceArea::calcExtForce(sead::Vector3f* force, const sead::Vector3f& pos,
const sead::Vector3f& prevForce,
const sead::Vector3f& velocity) const {
force->set(0.0f, 0.0f, 0.0f);
if (!isInVolume(pos))
return;
sead::Vector3f dirUp = {0.0f, 0.0f, 0.0f};
al::getAreaObjDirUp(&dirUp, this);
sead::Vector3f velH = {0.0f, 0.0f, 0.0f};
sead::Vector3f velV = {0.0f, 0.0f, 0.0f};
al::separateVectorHV(&velH, &velV, dirUp, velocity);
sead::Vector3f prevForceH = {0.0f, 0.0f, 0.0f};
sead::Vector3f prevForceV = {0.0f, 0.0f, 0.0f};
al::separateVectorHV(&prevForceH, &prevForceV, dirUp, prevForce);
f32 speedV = dirUp.dot(velV);
f32 prevForceMagnitudeV = dirUp.dot(prevForceV);
// --- Vertical force ---
sead::Vector3f forceV;
if (al::isSameSign(speedV, mSpeedVTarget) &&
sead::Mathf::abs(speedV) > sead::Mathf::abs(mSpeedVTarget)) {
forceV = dirUp * (-prevForceMagnitudeV);
} else {
f32 curSpeedV = speedV + prevForceMagnitudeV;
f32 newSpeedV = al::converge(curSpeedV, mSpeedVTarget, mSpeedVStep);
forceV = dirUp * (newSpeedV - curSpeedV);
}
// --- Horizontal force ---
sead::Vector3f dirVelH = {0.0f, 0.0f, 0.0f};
sead::Vector3f forceH;
if (al::tryNormalizeOrZero(&dirVelH, velH)) {
f32 diff = velH.length() - prevForceH.length();
f32 forceMag = sead::Mathf::clampMin(diff, 0.0f) * mForceH;
forceH = (dirVelH * forceMag) - (prevForceH + velH);
} else {
forceH = -prevForceH;
}
force->setAdd(forceV, forceH);
}

View file

@ -8,10 +8,11 @@ public:
void init(const al::AreaInitInfo& info) override;
void calcExtForce(sead::Vector3f*, const sead::Vector3f&, const sead::Vector3f&,
const sead::Vector3f&) const;
void calcExtForce(sead::Vector3f* force, const sead::Vector3f& pos,
const sead::Vector3f& prevForce, const sead::Vector3f& velocity) const;
private:
sead::Vector2f mUnknown;
f32 mMagnitude = 1.0;
f32 mSpeedVStep = 0.0f;
f32 mSpeedVTarget = 0.0f;
f32 mForceH = 1.0f;
};