Area: Implement MoveArea2D (#949)

This commit is contained in:
guymakinggames 2026-03-23 14:53:58 +00:00 committed by GitHub
parent cf148f369e
commit f6329cb6d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 220 additions and 21 deletions

View file

@ -1093,43 +1093,43 @@ Area/MoveArea2D.o:
- offset: 0x005f48
size: 84
label: _ZN10MoveArea2DC2EPKc
status: NotDecompiled
status: Matching
- offset: 0x005f9c
size: 96
label: _ZN10MoveArea2DC1EPKc
status: NotDecompiled
status: Matching
- offset: 0x005ffc
size: 244
label: _ZN10MoveArea2D4initERKN2al12AreaInitInfoE
status: NotDecompiled
status: Matching
- offset: 0x0060f0
size: 88
label: _ZNK10MoveArea2D13calcSnapPowerEPN4sead7Vector3IfEEPfRKS2_f
status: NotDecompiled
status: Matching
- offset: 0x006148
size: 296
label: _ZNK10MoveArea2D17calcSnapPowerCubeEPN4sead7Vector3IfEEPfRKS2_f
status: NotDecompiled
status: Matching
- offset: 0x006270
size: 276
label: _ZNK10MoveArea2D21calcSnapPowerCylinderEPN4sead7Vector3IfEEPfRKS2_f
status: NotDecompiled
status: Matching
- offset: 0x006384
size: 296
label: _ZNK10MoveArea2D17calcSnapPowerDiskEPN4sead7Vector3IfEEPfRKS2_f
status: NotDecompiled
status: Matching
- offset: 0x0064ac
size: 500
label: _ZNK10MoveArea2D14calcGravityDirEPN4sead7Vector3IfEEPfRKS2_
status: NotDecompiled
status: Matching
- offset: 0x0066a0
size: 56
label: _ZNK10MoveArea2D15calcGravityYDirEPN4sead7Vector3IfEEPf
status: NotDecompiled
status: Matching
- offset: 0x0066d8
size: 260
label: _ZNK10MoveArea2D29calcGravityCylinderCenterAxisEPN4sead7Vector3IfEEPfRKS2_b
status: NotDecompiled
status: Matching
Area/NpcForceMaterialCodeArea.o:
'.text':
- offset: 0x0067dc

182
src/Area/MoveArea2D.cpp Normal file
View file

@ -0,0 +1,182 @@
#include "Area/MoveArea2D.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"
MoveArea2D::MoveArea2D(const char* name) : al::AreaObj(name) {}
void MoveArea2D::init(const al::AreaInitInfo& info) {
al::AreaObj::init(info);
al::tryGetAreaObjArg(&mSurfaceDistance, this, "SurfaceDistance");
al::tryGetAreaObjArg(&mGravityOffset, this, "GravityOffset");
const char* shapeName = nullptr;
alPlacementFunction::tryGetModelName(&shapeName, info);
SnapGravityType gravityType = SnapGravityType::Default;
al::tryGetAreaObjArg((s32*)&gravityType, this, "SnapGravityType");
if (al::isEqualString(shapeName, "AreaCubeBase")) {
mShapeType = ShapeType::CubeBase;
} else if (al::isEqualString(shapeName, "AreaCylinder")) {
mShapeType = ShapeType::Cylinder;
} else if (al::isEqualString(shapeName, "AreaCylinderCenter")) {
switch (gravityType) {
case SnapGravityType::Default:
case SnapGravityType::Reverse:
mShapeType = ShapeType::CylinderCenterReverse;
break;
case SnapGravityType::Normal:
mShapeType = ShapeType::CylinderCenter;
break;
default:
mShapeType = ShapeType::CylinderCenterReverse;
break;
}
} else {
invalidate();
}
}
bool MoveArea2D::calcSnapPower(sead::Vector3f* outDir, f32* outPower, const sead::Vector3f& pos,
f32 surfaceDistance) const {
switch (mShapeType) {
case ShapeType::CubeBase:
return calcSnapPowerCube(outDir, outPower, pos, surfaceDistance);
case ShapeType::Cylinder:
return calcSnapPowerCylinder(outDir, outPower, pos, surfaceDistance);
case ShapeType::CylinderCenter:
return calcSnapPowerDisk(outDir, outPower, pos, surfaceDistance);
case ShapeType::CylinderCenterReverse:
return calcSnapPowerDisk(outDir, outPower, pos, surfaceDistance);
default:
return false;
}
}
bool MoveArea2D::calcSnapPowerDisk(sead::Vector3f* outDir, f32* outPower, const sead::Vector3f& pos,
f32 surfaceDistance) const {
const sead::Matrix34f& mtx = getAreaMtx();
sead::Vector3f axis = mtx.getBase(1);
sead::Vector3f diff = mtx.getTranslation() - pos;
f32 distance = axis.dot(diff);
f32 power;
if (al::isNearZeroOrLess(distance)) {
*outDir = -axis;
power = sead::Mathf::abs(distance) - surfaceDistance;
} else {
*outDir = axis;
power = sead::Mathf::abs(distance) + surfaceDistance;
}
if (!al::isNearZeroOrGreater(power)) {
outDir->negate();
power = -power;
}
*outPower = power;
return true;
}
bool MoveArea2D::calcSnapPowerCube(sead::Vector3f* outDir, f32* outPower, const sead::Vector3f& pos,
f32 surfaceDistance) const {
const sead::Matrix34f& mtx = getAreaMtx();
sead::Vector3f axis = mtx.getBase(2);
sead::Vector3f diff = mtx.getTranslation() - pos;
f32 distance = axis.dot(diff);
f32 power;
if (al::isNearZeroOrLess(distance)) {
*outDir = -axis;
power = sead::Mathf::abs(distance) - surfaceDistance;
} else {
*outDir = axis;
power = sead::Mathf::abs(distance) + surfaceDistance;
}
if (!al::isNearZeroOrGreater(power)) {
outDir->negate();
power = -power;
}
*outPower = power;
return true;
}
bool MoveArea2D::calcSnapPowerCylinder(sead::Vector3f* dirH, f32* outPower,
const sead::Vector3f& pos, f32 surfaceDistance) const {
const sead::Matrix34f& mtx = getAreaMtx();
sead::Vector3f offH = mtx.getTranslation();
offH -= pos;
sead::Vector3f upAxis;
mtx.getBase(upAxis, 1);
al::verticalizeVec(&offH, upAxis, offH);
if (!al::tryNormalizeOrZero(dirH, offH))
return false;
f32 delta = offH.length() - surfaceDistance;
if (!al::isNearZeroOrGreater(delta)) {
dirH->negate();
delta = -delta;
}
*outPower = delta;
return true;
}
bool MoveArea2D::calcGravityDir(sead::Vector3f* outDir, f32* outDist,
const sead::Vector3f& pos) const {
switch (mShapeType) {
case ShapeType::CubeBase:
return calcGravityYDir(outDir, outDist);
case ShapeType::Cylinder:
return calcGravityYDir(outDir, outDist);
case ShapeType::CylinderCenter:
return calcGravityCylinderCenterAxis(outDir, outDist, pos, false);
case ShapeType::CylinderCenterReverse:
return calcGravityCylinderCenterAxis(outDir, outDist, pos, true);
default:
return false;
}
}
bool MoveArea2D::calcGravityYDir(sead::Vector3f* outDir, f32* outDist) const {
const sead::Matrix34f& mtx = getAreaMtx();
mtx.getBase(*outDir, 1);
outDir->negate();
*outDist = 1.0f;
return true;
}
bool MoveArea2D::calcGravityCylinderCenterAxis(sead::Vector3f* dirH, f32* outDist,
const sead::Vector3f& pos, bool isReverse) const {
const sead::Matrix34f& mtx = getAreaMtx();
sead::Vector3f offH = mtx.getTranslation();
offH -= pos;
*outDist = offH.length();
sead::Vector3f upAxis;
mtx.getBase(upAxis, 1);
al::verticalizeVec(&offH, upAxis, offH);
if (!al::tryNormalizeOrZero(dirH, offH)) {
*outDist = 0.0f;
*dirH = {0.0f, 0.0f, 0.0f};
return false;
}
if (isReverse)
dirH->negate();
return true;
}

View file

@ -6,23 +6,40 @@
class MoveArea2D : public al::AreaObj {
public:
enum class ShapeType { Cube = 1, Cylinder, CylinderCenter, Disk };
enum class ShapeType {
None = 0,
CubeBase = 1,
Cylinder = 2,
CylinderCenter = 3,
CylinderCenterReverse = 4,
};
enum class SnapGravityType {
Default = 0,
Normal = 1,
Reverse = 2,
};
MoveArea2D(const char* name);
void init(const al::AreaInitInfo& info) override;
bool calcGravityCylinderCenterAxis(sead::Vector3f*, f32*, const sead::Vector3f&, bool) const;
bool calcGravityDir(sead::Vector3f*, f32*, const sead::Vector3f&) const;
bool calcGravityYDir(sead::Vector3f*, f32*) const;
bool calcGravityCylinderCenterAxis(sead::Vector3f* dirH, f32* outDist,
const sead::Vector3f& pos, bool isReverse) const;
bool calcGravityDir(sead::Vector3f* outDir, f32* outDist, const sead::Vector3f& pos) const;
bool calcGravityYDir(sead::Vector3f* outDir, f32* outDist) const;
bool calcSnapPower(sead::Vector3f*, f32*, const sead::Vector3f&, f32);
bool calcSnapPowerCube(sead::Vector3f*, f32*, const sead::Vector3f&, f32);
bool calcSnapPowerCylinder(sead::Vector3f*, f32*, const sead::Vector3f&, f32);
bool calcSnapPowerDisk(sead::Vector3f*, f32*, const sead::Vector3f&, f32);
bool calcSnapPower(sead::Vector3f* outDir, f32* outPower, const sead::Vector3f& pos,
f32 surfaceDistance) const;
bool calcSnapPowerCube(sead::Vector3f* outDir, f32* outPower, const sead::Vector3f& pos,
f32 surfaceDistance) const;
bool calcSnapPowerCylinder(sead::Vector3f* dirH, f32* outPower, const sead::Vector3f& pos,
f32 surfaceDistance) const;
bool calcSnapPowerDisk(sead::Vector3f* outDir, f32* outPower, const sead::Vector3f& pos,
f32 surfaceDistance) const;
private:
ShapeType mShapeType;
f32 mSurfaceDistance;
f32 mGravityOffset;
ShapeType mShapeType = ShapeType::None;
f32 mSurfaceDistance = 0.0f;
f32 mGravityOffset = 0.0f;
};