From 8d56ef3667f9e8dee00b609c5825221577bd61ae Mon Sep 17 00:00:00 2001 From: guymakinggames <66076221+guymakinggames@users.noreply.github.com> Date: Sat, 18 Apr 2026 22:34:01 +0100 Subject: [PATCH] Player: Implement PlayerStateBind --- data/file_list.yml | 36 +++++----- src/Player/PlayerPuppet.h | 19 +++-- src/Player/PlayerStateBind.cpp | 127 +++++++++++++++++++++++++++++++++ src/Player/PlayerStateBind.h | 42 +++++++++++ 4 files changed, 202 insertions(+), 22 deletions(-) create mode 100644 src/Player/PlayerStateBind.cpp create mode 100644 src/Player/PlayerStateBind.h diff --git a/data/file_list.yml b/data/file_list.yml index 64c53263..ae96fd95 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -125934,80 +125934,80 @@ Player/PlayerStateBind.o: label: - _ZN15PlayerStateBindC1EPN2al9LiveActorEPK11PlayerConstPK11PlayerInputPK12PlayerPuppetPK19IUsePlayerCollisionP13PlayerTrigger - _ZN15PlayerStateBindC2EPN2al9LiveActorEPK11PlayerConstPK11PlayerInputPK12PlayerPuppetPK19IUsePlayerCollisionP13PlayerTrigger - status: NotDecompiled + status: Matching - offset: 0x467288 size: 184 label: _ZN15PlayerStateBind6appearEv - status: NotDecompiled + status: Matching - offset: 0x467340 size: 144 label: _ZN15PlayerStateBind7endBindEv - status: NotDecompiled + status: Matching - offset: 0x4673d0 size: 4 label: _ZN15PlayerStateBind7exeBindEv - status: NotDecompiled + status: Matching - offset: 0x4673d4 size: 152 label: _ZN15PlayerStateBind14exeEndOnGroundEv - status: NotDecompiled + status: Matching - offset: 0x46746c size: 172 label: _ZN15PlayerStateBind10exeEndJumpEv - status: NotDecompiled + status: Matching - offset: 0x467518 size: 152 label: _ZN15PlayerStateBind14exeEndCapThrowEv - status: NotDecompiled + status: Matching - offset: 0x4675b0 size: 160 label: _ZN15PlayerStateBind10exeEndFallEv - status: NotDecompiled + status: Matching - offset: 0x467650 size: 72 label: _ZNK15PlayerStateBind13isEndOnGroundEv - status: NotDecompiled + status: Matching - offset: 0x467698 size: 96 label: _ZNK15PlayerStateBind8isEndAirEv - status: NotDecompiled + status: Matching - offset: 0x4676f8 size: 72 label: _ZNK15PlayerStateBind13isEndCapThrowEv - status: NotDecompiled + status: Matching - offset: 0x467740 size: 80 label: _ZNK15PlayerStateBind14isInvalidInputEv - status: NotDecompiled + status: Matching - offset: 0x467790 size: 36 label: _ZN15PlayerStateBindD0Ev - status: NotDecompiled + status: Matching lazy: true - offset: 0x4677b4 size: 4 label: _ZNK12_GLOBAL__N_122PlayerStateBindNrvBind7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x4677b8 size: 156 label: _ZNK12_GLOBAL__N_129PlayerStateBindNrvEndOnGround7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x467854 size: 8 label: _ZNK12_GLOBAL__N_125PlayerStateBindNrvEndJump7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x46785c size: 156 label: _ZNK12_GLOBAL__N_129PlayerStateBindNrvEndCapThrow7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x4678f8 size: 8 label: _ZNK12_GLOBAL__N_125PlayerStateBindNrvEndFall7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true Player/PlayerStateCameraSubjective.o: '.text': diff --git a/src/Player/PlayerPuppet.h b/src/Player/PlayerPuppet.h index d1285aca..43b811b5 100644 --- a/src/Player/PlayerPuppet.h +++ b/src/Player/PlayerPuppet.h @@ -25,6 +25,12 @@ class PlayerEffect; class PlayerInput; class WorldEndBorderKeeper; +struct PlayerBindEndJumpInfo { + sead::Vector3f endTrans; + s32 endFrame; + f32 gravity; +}; + class PlayerPuppet : public IUsePlayerPuppet { public: PlayerPuppet(al::LiveActor*, HackCap*, PlayerAnimator*, IUsePlayerCollision*, @@ -80,6 +86,11 @@ public: const al::AreaObj*); bool tryUpdateRecoveryInfo(bool*, bool*, sead::Vector3f*, sead::Vector3f*, const al::AreaObj**); bool isBinding() const; + + bool isBindEndCapThrow() const { return mIsBindEndCapThrow; } + + const PlayerBindEndJumpInfo* getBindEndJumpInfo() const { return mBindEndJumpInfo; } + bool isNoCollide() const; private: @@ -106,7 +117,7 @@ private: al::AreaObj* mAreaObj; bool mIsBindEndOnGround; bool mIsBindEndJump; - bool _aa; + bool mIsBindEndCapThrow; bool mIsValidCollisionCheck; bool _ac; bool mIsRequestDamage; @@ -120,9 +131,9 @@ private: bool _b5; bool _b6; - char filler[0x8]; - - sead::Vector3f _c8; + char filler[0x10]; + PlayerBindEndJumpInfo* mBindEndJumpInfo; }; +static_assert(sizeof(PlayerBindEndJumpInfo) == 0x14); static_assert(sizeof(PlayerPuppet) == 0xd0); diff --git a/src/Player/PlayerStateBind.cpp b/src/Player/PlayerStateBind.cpp new file mode 100644 index 00000000..538f355d --- /dev/null +++ b/src/Player/PlayerStateBind.cpp @@ -0,0 +1,127 @@ +#include "Player/PlayerStateBind.h" + +#include "Library/LiveActor/ActorMovementFunction.h" +#include "Library/LiveActor/ActorPoseUtil.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveStateBase.h" +#include "Library/Nerve/NerveUtil.h" + +#include "Player/PlayerActionAirMoveControl.h" +#include "Player/PlayerConst.h" +#include "Player/PlayerPuppet.h" +#include "Player/PlayerTrigger.h" + +namespace { +NERVE_IMPL(PlayerStateBind, Bind) +NERVE_IMPL(PlayerStateBind, EndOnGround) +NERVE_IMPL(PlayerStateBind, EndJump) +NERVE_IMPL(PlayerStateBind, EndCapThrow) +NERVE_IMPL(PlayerStateBind, EndFall) + +NERVES_MAKE_NOSTRUCT(PlayerStateBind, Bind, EndOnGround, EndJump, EndCapThrow, EndFall) +} // namespace + +PlayerStateBind::PlayerStateBind(al::LiveActor* player, const PlayerConst* playerConst, + const PlayerInput* input, const PlayerPuppet* playerPuppet, + const IUsePlayerCollision* collision, PlayerTrigger* trigger) + : al::ActorStateBase("バインド", player), mConst(playerConst), mPuppet(playerPuppet), + mTrigger(trigger) { + mAirMoveControl = new PlayerActionAirMoveControl(player, playerConst, input, collision, false); + initNerve(&Bind, 0); +} + +void PlayerStateBind::appear() { + al::setVelocityZero(mActor); + + if (mPuppet->isBinding()) + al::setNerve(this, &Bind); + else + endBind(); + + al::NerveStateBase::appear(); +} + +void PlayerStateBind::endBind() { + if (mPuppet->isBindEndOnGround()) + al::setNerve(this, &EndOnGround); + else if (mPuppet->isBindEndJump()) + al::setNerve(this, &EndJump); + else if (mPuppet->isBindEndCapThrow()) + al::setNerve(this, &EndCapThrow); + else + al::setNerve(this, &EndFall); +} + +void PlayerStateBind::exeBind() {} + +void PlayerStateBind::exeEndOnGround() { + if (al::isFirstStep(this)) + mTrigger->set(PlayerTrigger::EActionTrigger_val3); + + al::tryAddVelocityLimit(mActor, al::getGravity(mActor) * mConst->getGravityAir(), + mConst->getFallSpeedMax()); +} + +void PlayerStateBind::exeEndJump() { + if (al::isFirstStep(this)) { + mTrigger->set(PlayerTrigger::EActionTrigger_val3); + + const PlayerBindEndJumpInfo* bindEndJumpInfo = mPuppet->getBindEndJumpInfo(); + al::setVelocity(mActor, bindEndJumpInfo->endTrans); + + mAirMoveControl->setup(10000.0f, mConst->getJumpMoveSpeedMin(), 0, al::calcSpeedV(mActor), + bindEndJumpInfo->gravity, bindEndJumpInfo->endFrame, 0.0f); + } + + mAirMoveControl->update(); +} + +void PlayerStateBind::exeEndCapThrow() { + if (al::isFirstStep(this)) + mTrigger->set(PlayerTrigger::EActionTrigger_val3); + + al::tryAddVelocityLimit(mActor, al::getGravity(mActor) * mConst->getGravityAir(), + mConst->getFallSpeedMax()); +} + +void PlayerStateBind::exeEndFall() { + if (al::isFirstStep(this)) { + mTrigger->set(PlayerTrigger::EActionTrigger_val3); + + mAirMoveControl->setup(10000.0f, mConst->getJumpMoveSpeedMin(), 0, al::calcSpeedV(mActor), + mConst->getJumpGravity(), 0, 0.0f); + } + + mAirMoveControl->update(); +} + +bool PlayerStateBind::isEndOnGround() const { + if (al::isNerve(this, &Bind)) + return false; + + return al::isNerve(this, &EndOnGround); +} + +bool PlayerStateBind::isEndAir() const { + if (al::isNerve(this, &Bind)) + return false; + + if (al::isNerve(this, &EndJump)) + return true; + + return al::isNerve(this, &EndFall); +} + +bool PlayerStateBind::isEndCapThrow() const { + if (al::isNerve(this, &Bind)) + return false; + + return al::isNerve(this, &EndCapThrow); +} + +bool PlayerStateBind::isInvalidInput() const { + if (!al::isNerve(this, &EndJump)) + return false; + + return al::isLessEqualStep(this, mPuppet->getBindEndJumpInfo()->endFrame); +} diff --git a/src/Player/PlayerStateBind.h b/src/Player/PlayerStateBind.h new file mode 100644 index 00000000..13646a7a --- /dev/null +++ b/src/Player/PlayerStateBind.h @@ -0,0 +1,42 @@ +#pragma once + +#include "Library/Nerve/NerveStateBase.h" + +namespace al { +class LiveActor; +} + +class IUsePlayerCollision; +class PlayerActionAirMoveControl; +class PlayerConst; +class PlayerInput; +class PlayerPuppet; +class PlayerTrigger; + +class PlayerStateBind : public al::ActorStateBase { +public: + PlayerStateBind(al::LiveActor* player, const PlayerConst* playerConst, const PlayerInput* input, + const PlayerPuppet* playerPuppet, const IUsePlayerCollision* collision, + PlayerTrigger* trigger); + + void appear() override; + + void endBind(); + void exeBind(); + void exeEndOnGround(); + void exeEndJump(); + void exeEndCapThrow(); + void exeEndFall(); + bool isEndOnGround() const; + bool isEndAir() const; + bool isEndCapThrow() const; + bool isInvalidInput() const; + +private: + const PlayerConst* mConst = nullptr; + const PlayerPuppet* mPuppet = nullptr; + PlayerTrigger* mTrigger = nullptr; + PlayerActionAirMoveControl* mAirMoveControl = nullptr; +}; + +static_assert(sizeof(PlayerStateBind) == 0x40);