Player: Implement PlayerStateSquat (#697)

This commit is contained in:
MonsterDruide1 2025-07-25 18:01:22 +02:00 committed by GitHub
parent 95ffa5e4b0
commit 13516553b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 354 additions and 16 deletions

View file

@ -128328,63 +128328,63 @@ Player/PlayerStateSquat.o:
label:
- _ZN16PlayerStateSquatC1EPN2al9LiveActorEPK11PlayerConstP14PlayerAnimatorPK11PlayerInputPK19IUsePlayerCollisionPK19IPlayerModelChangerPK13PlayerTriggerP6IJudgeSL_SL_
- _ZN16PlayerStateSquatC2EPN2al9LiveActorEPK11PlayerConstP14PlayerAnimatorPK11PlayerInputPK19IUsePlayerCollisionPK19IPlayerModelChangerPK13PlayerTriggerP6IJudgeSL_SL_
status: NotDecompiled
status: Matching
- offset: 0x483580
size: 144
label: _ZN16PlayerStateSquat6appearEv
status: NotDecompiled
status: Matching
- offset: 0x483610
size: 176
label: _ZNK16PlayerStateSquat16isEnableLongJumpEv
status: NotDecompiled
status: Matching
- offset: 0x4836c0
size: 1320
label: _ZN16PlayerStateSquat8exeBrakeEv
status: NotDecompiled
status: Matching
- offset: 0x483be8
size: 88
label: _ZN16PlayerStateSquat21setNerveStandUpOrKillEv
status: NotDecompiled
status: Matching
- offset: 0x483c40
size: 384
label: _ZN16PlayerStateSquat7exeWaitEv
status: NotDecompiled
status: Matching
- offset: 0x483dc0
size: 284
label: _ZN16PlayerStateSquat14fixPressRumbleEv
status: NotDecompiled
status: Matching
- offset: 0x483edc
size: 744
label: _ZN16PlayerStateSquat7exeWalkEv
status: NotDecompiled
status: Matching
- offset: 0x4841c4
size: 296
label: _ZN16PlayerStateSquat10exeStandUpEv
status: NotDecompiled
status: Matching
- offset: 0x4842ec
size: 36
label: _ZN16PlayerStateSquatD0Ev
status: NotDecompiled
status: Matching
lazy: true
- offset: 0x484310
size: 8
label: _ZNK12_GLOBAL__N_123PlayerStateSquatNrvWait7executeEPN2al11NerveKeeperE
status: NotDecompiled
status: Matching
guess: true
- offset: 0x484318
size: 8
label: _ZNK12_GLOBAL__N_124PlayerStateSquatNrvBrake7executeEPN2al11NerveKeeperE
status: NotDecompiled
status: Matching
guess: true
- offset: 0x484320
size: 8
label: _ZNK12_GLOBAL__N_123PlayerStateSquatNrvWalk7executeEPN2al11NerveKeeperE
status: NotDecompiled
status: Matching
guess: true
- offset: 0x484328
size: 8
label: _ZNK12_GLOBAL__N_126PlayerStateSquatNrvStandUp7executeEPN2al11NerveKeeperE
status: NotDecompiled
status: Matching
guess: true
Player/PlayerStateSwim.o:
'.text':

View file

@ -1,5 +1,6 @@
#pragma once
#include <container/seadRingBuffer.h>
#include <math/seadVector.h>
namespace al {
@ -15,8 +16,34 @@ public:
void calcTilt(sead::Vector3f*, const sead::Vector3f&, f32);
void calcTurnPowerRate(const sead::Vector3f&) const;
void set_88(bool value) { _88 = value; }
const sead::Vector3f& get_5c() const { return _5c; }
bool get_69() const { return _69; }
private:
void* filler[0x90 / 8];
al::LiveActor* mPlayer;
f32 _8 = 0.0f;
sead::Vector3f _c = {0.0f, 0.0f, 0.0f};
sead::Vector3f _18 = {0.0f, 0.0f, 0.0f};
sead::Vector3f _24 = {0.0f, 0.0f, 0.0f};
f32 _30 = 0.0f;
sead::RingBuffer<f32> _38;
sead::Vector3f _50 = {0.0f, 0.0f, 0.0f};
sead::Vector3f _5c = {0.0f, 0.0f, 0.0f};
bool _68 = false;
bool _69 = false;
bool _6a = false;
f32 mTurnAngleStart = 0.0f;
f32 mTurnAngleFast = 0.0f;
f32 mTurnAngleLimit = 0.0f;
f32 mTurnAngleFastLimit = 0.0f;
s32 mTurnAccelFrame = 0;
s32 mTurnAccelFrameFast = 0;
s32 mTurnBrakeFrame = 0;
bool _88 = false;
bool _89 = false;
};
static_assert(sizeof(PlayerActionTurnControl) == 0x90);

View file

@ -0,0 +1,258 @@
#include "Player/PlayerStateSquat.h"
#include "Library/LiveActor/ActorMovementFunction.h"
#include "Library/LiveActor/ActorPoseKeeper.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/Math/MathUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Player/IPlayerModelChanger.h"
#include "Player/PlayerActionTurnControl.h"
#include "Player/PlayerActionVelocityControl.h"
#include "Player/PlayerAnimator.h"
#include "Player/PlayerConst.h"
#include "Player/PlayerInput.h"
#include "Player/PlayerTrigger.h"
#include "Util/JudgeUtil.h"
#include "Util/ObjUtil.h"
#include "Util/PlayerCollisionUtil.h"
namespace {
NERVE_IMPL(PlayerStateSquat, Brake);
NERVE_IMPL(PlayerStateSquat, Wait);
NERVE_IMPL(PlayerStateSquat, Walk);
NERVE_IMPL(PlayerStateSquat, StandUp);
NERVES_MAKE_NOSTRUCT(PlayerStateSquat, Brake);
NERVES_MAKE_STRUCT(PlayerStateSquat, Wait, Walk, StandUp);
} // namespace
PlayerStateSquat::PlayerStateSquat(al::LiveActor* player, const PlayerConst* pConst,
PlayerAnimator* animator, const PlayerInput* input,
const IUsePlayerCollision* collider,
const IPlayerModelChanger* modelChanger,
const PlayerTrigger* trigger, IJudge* judgeStartSquat,
IJudge* judgeStartRun, IJudge* judgeEnableStandUp)
: al::ActorStateBase("しゃがみ", player), mConst(pConst), mAnimator(animator), mInput(input),
mCollision(collider), mModelChanger(modelChanger), mTrigger(trigger),
mActionTurnControl(new PlayerActionTurnControl(player)), mJudgeStartSquat(judgeStartSquat),
mJudgeStartRun(judgeStartRun), mJudgeEnableStandUp(judgeEnableStandUp) {
const PlayerConst* lConst = mConst;
mActionTurnControl->setup(lConst->getRoundMinDegree(), 180.0f, lConst->getSquatWalkTurnSpeed(),
lConst->getSquatWalkTurnSpeed(), lConst->getSquatWalkTurnFrame(), 1,
lConst->getSquatWalkTurnFrame());
mActionTurnControl->set_88(true);
initNerve(&NrvPlayerStateSquat.Wait, 0);
}
void PlayerStateSquat::appear() {
al::ActorStateBase::appear();
mIsSkipSquatStartAnim =
mAnimator->isAnim("RollingEnd") || mTrigger->isOn(PlayerTrigger::EActionTrigger_val12);
if (mAnimator->isSubAnimPlaying())
mAnimator->endSubAnim();
al::setNerve(this, &Brake);
}
bool PlayerStateSquat::isEnableLongJump() const {
if (isDead())
return false;
if (!al::isNerve(this, &Brake) || mModelChanger->is2DModel())
return false;
sead::Vector3f front = {0.0f, 0.0f, 0.0f};
al::calcFrontDir(&front, mActor);
return front.dot(al::getVelocity(mActor)) > 0.0f;
}
void PlayerStateSquat::setNerveStandUpOrKill() {
if (mModelChanger->is2DModel())
kill();
else
al::setNerve(this, &NrvPlayerStateSquat.StandUp);
}
void PlayerStateSquat::fixPressRumble() {
if (!rs::isCollidedGround(mCollision) || !rs::isCollidedCeiling(mCollision))
return;
const sead::Vector3f& groundNormal = rs::getCollidedGroundNormal(mCollision);
const sead::Vector3f& ceilingNormal = rs::getCollidedCeilingNormal(mCollision);
if (!al::isReverseDirection(groundNormal, ceilingNormal))
return;
al::LiveActor* actor = mActor;
f32 distanceClippedIntoGround = sead::Mathf::clampMin(
(rs::getCollidedGroundPos(mCollision) - al::getTrans(actor)).dot(groundNormal), 0.0f);
// instead of pulling Mario up by half the current "clip distance",
// it clips him further into the ground by this amount. This is probably correct, because being
// pushed up by the ground will move Mario up even further, so in total, he is
// moved upwards (out of the ground) by about half the clip distance.
al::setTrans(actor, al::getTrans(actor) - (groundNormal * (distanceClippedIntoGround * 0.5f)));
}
void PlayerStateSquat::exeBrake() {
sead::Vector3f up = {0.0f, 0.0f, 0.0f};
rs::calcGroundNormalOrUpDir(&up, mActor, mCollision);
bool isSkate = rs::isOnGroundSkateCode(mActor, mCollision);
if (al::isFirstStep(this)) {
if (mModelChanger->is2DModel() || mIsSkipSquatStartAnim)
mAnimator->startAnim("SquatWait");
else
mAnimator->startAnim("SquatStart");
sead::Vector3f velPlane = {0.0f, 0.0f, 0.0f};
sead::Vector3f velUp = {0.0f, 0.0f, 0.0f};
al::separateVectorParallelVertical(&velUp, &velPlane, up, al::getVelocity(mActor));
sead::Vector3f front = {0.0f, 0.0f, 0.0f};
al::calcFrontDir(&front, mActor);
al::verticalizeVec(&front, up, front);
al::tryNormalizeOrZero(&front);
f32 dot = front.dot(velPlane);
if (dot < 0.0f && !isSkate) {
velPlane -= front * dot;
dot = 0.0f;
}
f32 hSpeed = velPlane.length();
if (hSpeed <= mConst->getNormalMaxSpeed() && dot > 0.0f) {
f32 squatAccelRate = mConst->getSquatAccelRate();
f32 squatBrakeEndSpeed = mConst->getSquatBrakeEndSpeed();
f32 accelRateTimesHSpeed = squatAccelRate * hSpeed;
if (accelRateTimesHSpeed <= squatBrakeEndSpeed)
accelRateTimesHSpeed = 0.0f;
f32 hSpeed2 = velPlane.length();
if (hSpeed2 > 0.0f)
velPlane *= (accelRateTimesHSpeed / hSpeed2);
}
al::setVelocity(mActor, velPlane + velUp);
}
sead::Vector3f moveInput = {0.0f, 0.0f, 0.0f};
mInput->calcMoveInput(&moveInput, up);
sead::Vector3f inertiaSlide = {0.0f, 0.0f, 0.0f};
if (isSkate) {
rs::moveInertiaSlideOnSkate(
&inertiaSlide, mActor, mCollision, moveInput, mConst->getSquatBrakeRateOnSkate(),
mConst->getSquatBrakeSideAccelOnSkate(), mConst->getSquatBrakeSideRateOnSkate(),
mConst->getSquatBrakeSideMaxSpeedRate(), mConst->getGravity(), mConst->getGravityAir(),
mConst->getFallSpeedMax());
} else {
rs::moveInertiaSlide(&inertiaSlide, mActor, mCollision, moveInput,
mConst->getSquatBrakeRate(), mConst->getSquatBrakeSideAccel(),
mConst->getSquatBrakeSideRate(),
mConst->getSquatBrakeSideMaxSpeedRate(), mConst->getGravity(),
mConst->getGravityAir(), mConst->getFallSpeedMax());
}
rs::slerpUp(mActor, up, mConst->getSlerpQuatRate(), mConst->getHillPoseDegreeMax());
if (inertiaSlide.length() <= mConst->getSquatBrakeEndSpeed()) {
al::setVelocityZeroH(mActor);
al::setNerve(this, &NrvPlayerStateSquat.Wait);
return;
}
if (!rs::updateJudgeAndResult(mJudgeStartSquat) &&
rs::updateJudgeAndResult(mJudgeEnableStandUp)) {
setNerveStandUpOrKill();
}
}
void PlayerStateSquat::exeWait() {
if (al::isFirstStep(this) && !mModelChanger->is2DModel())
mAnimator->startAnim("SquatWait");
fixPressRumble();
rs::waitGround(mActor, mCollision, mConst->getGravity(), mConst->getFallSpeedMax(),
mConst->getSlerpQuatRate(), mConst->getWaitPoseDegreeMax());
bool startSquat = rs::updateJudgeAndResult(mJudgeStartSquat);
bool enableStandUp = rs::updateJudgeAndResult(mJudgeEnableStandUp);
if (!startSquat && enableStandUp) {
setNerveStandUpOrKill();
return;
}
if (rs::updateJudgeAndResult(mJudgeStartRun) && !mModelChanger->is2DModel())
al::setNerve(this, &NrvPlayerStateSquat.Walk);
}
void PlayerStateSquat::exeWalk() {
al::LiveActor* actor = mActor;
if (al::isFirstStep(this)) {
mAnimator->startAnim("SquatWalk");
mActionTurnControl->reset();
}
sead::Vector3f up = {0.0f, 0.0f, 0.0f};
rs::calcGroundNormalOrUpDir(&up, actor, mCollision);
if (rs::isCollidedGround(mCollision)) {
PlayerActionVelocityControl velocityControl = {actor, mCollision};
velocityControl.calcOnGround(up);
velocityControl.apply();
}
if (!rs::updateJudgeAndResult(mJudgeStartSquat) &&
rs::updateJudgeAndResult(mJudgeEnableStandUp)) {
setNerveStandUpOrKill();
// BUG: missing return here => Squat state can affect for one more frame
}
if (!mInput->isMove()) {
al::setVelocity(actor, up * -mConst->getGravityMove());
al::setNerve(this, &NrvPlayerStateSquat.Wait);
return;
}
sead::Vector3f unkDir = {0.0f, 0.0f, 0.0f};
sead::Vector3f moveDir = {0.0f, 0.0f, 0.0f};
sead::Vector3f moveInput = {0.0f, 0.0f, 0.0f};
mInput->calcMoveInput(&moveInput, up);
mActionTurnControl->update(moveInput, up);
// TODO: rename these variables (unk and unkDir)
bool unk = mActionTurnControl->get_69();
unkDir.set(mActionTurnControl->get_5c());
if (!unk || !al::tryNormalizeOrZero(&moveDir, moveInput))
moveDir.set(unkDir);
sead::Vector3f velocity = al::getVelocity(mActor);
sead::Vector3f velPlane = {0.0f, 0.0f, 0.0f};
sead::Vector3f velUp = {0.0f, 0.0f, 0.0f};
al::separateVectorParallelVertical(&velUp, &velPlane, up, velocity);
if (!al::isNearZero(moveInput, 0.001f))
velPlane = mConst->getSquatWalkSpeed() * moveDir;
velUp = up * -mConst->getGravityMove();
al::setVelocity(mActor, velUp + velPlane);
rs::slerpUpFront(mActor, up, unkDir, mConst->getSlerpQuatRate(),
mConst->getHillPoseDegreeMax());
}
void PlayerStateSquat::exeStandUp() {
if (al::isFirstStep(this)) {
mAnimator->startAnim("SquatEnd");
al::setVelocityZeroH(mActor);
}
rs::waitGround(mActor, mCollision, mConst->getGravity(), mConst->getFallSpeedMax(),
mConst->getSlerpQuatRate(), mConst->getWaitPoseDegreeMax());
if (!rs::updateJudgeAndResult(mJudgeEnableStandUp)) {
al::setNerve(this, &Brake);
return;
}
if (rs::updateJudgeAndResult(mJudgeStartRun) || mAnimator->isAnimEnd())
kill();
}

View file

@ -0,0 +1,44 @@
#pragma once
#include "Library/Nerve/NerveStateBase.h"
class PlayerConst;
class PlayerAnimator;
class PlayerInput;
class IUsePlayerCollision;
class IPlayerModelChanger;
class PlayerTrigger;
class PlayerActionTurnControl;
class IJudge;
class PlayerStateSquat : public al::ActorStateBase {
public:
PlayerStateSquat(al::LiveActor* player, const PlayerConst* pConst, PlayerAnimator* animator,
const PlayerInput* input, const IUsePlayerCollision* collider,
const IPlayerModelChanger* modelChanger, const PlayerTrigger* trigger,
IJudge* judgeStartSquat, IJudge* judgeStartRun, IJudge* judgeEnableStandUp);
void appear() override;
bool isEnableLongJump() const;
void setNerveStandUpOrKill();
void fixPressRumble();
void exeBrake();
void exeWait();
void exeWalk();
void exeStandUp();
private:
const PlayerConst* mConst;
PlayerAnimator* mAnimator;
const PlayerInput* mInput;
const IUsePlayerCollision* mCollision;
const IPlayerModelChanger* mModelChanger;
const PlayerTrigger* mTrigger;
PlayerActionTurnControl* mActionTurnControl;
IJudge* mJudgeStartSquat;
IJudge* mJudgeStartRun;
IJudge* mJudgeEnableStandUp;
bool mIsSkipSquatStartAnim = false;
};

View file

@ -26,6 +26,8 @@ public:
EActionTrigger_val6 = 6,
// used in PlayerJudgeForceLand
EActionTrigger_val11 = 11,
// used in PlayerStateSquat
EActionTrigger_val12 = 12,
// used in PlayerJudgeWallCatch, PlayerJudgeWallKeep
EActionTrigger_val30 = 30,
EActionTrigger_QuickTurn = 34,

View file

@ -64,4 +64,11 @@ void moveDivingJump(al::LiveActor*, const sead::Vector3f&, f32, f32, f32, f32, f
void sendPlayerCollisionTouchMsg(const al::LiveActor*, al::HitSensor*, const IUsePlayerCollision*);
bool calcAlongSkyFront(sead::Vector3f*, const al::LiveActor*);
void calcGroundNormalOrUpDir(sead::Vector3f*, const al::LiveActor*, const IUsePlayerCollision*);
void moveInertiaSlide(sead::Vector3f*, al::LiveActor*, const IUsePlayerCollision*,
const sead::Vector3f&, f32, f32, f32, f32, f32, f32, f32);
void moveInertiaSlideOnSkate(sead::Vector3f*, al::LiveActor*, const IUsePlayerCollision*,
const sead::Vector3f&, f32, f32, f32, f32, f32, f32, f32);
} // namespace rs

View file

@ -254,7 +254,7 @@ def common_sead_math_template(c, path):
continue
if "using" in line or "typedef" in line:
continue
if "sead::Buffer" in line: # probably needs more exceptions at some point
if "sead::Buffer" in line or "sead::RingBuffer" in line: # probably needs more exceptions at some point
continue
if "sead::PtrArray" in line:
continue