diff --git a/include/MetroidPrime/CAnimData.hpp b/include/MetroidPrime/CAnimData.hpp index 6e335275..93e89c48 100644 --- a/include/MetroidPrime/CAnimData.hpp +++ b/include/MetroidPrime/CAnimData.hpp @@ -94,6 +94,7 @@ public: float GetAnimationDuration(int animIn) const; // GetAnimTimeRemaining__9CAnimDataCFRCQ24rstl66basic_string,Q24rstl17rmemory_allocator> // IsAnimTimeRemaining__9CAnimDataCFfRCQ24rstl66basic_string,Q24rstl17rmemory_allocator> + bool IsAnimTimeRemaining(float, const rstl::string&) const; // GetLocatorTransform__9CAnimDataCFRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>PC13CCharAnimTime // GetLocatorTransform__9CAnimDataCF6CSegIdPC13CCharAnimTime // CalcPlaybackAlignmentParms__9CAnimDataFRC18CAnimPlaybackParmsRCQ24rstl25ncrc_ptr<13CAnimTreeNode> diff --git a/include/MetroidPrime/CAxisAngle.hpp b/include/MetroidPrime/CAxisAngle.hpp index 156f32b4..bd11eed8 100644 --- a/include/MetroidPrime/CAxisAngle.hpp +++ b/include/MetroidPrime/CAxisAngle.hpp @@ -11,6 +11,8 @@ public: CAxisAngle(f32 x, f32 y, f32 z) : mVector(x, y, z) {} explicit CAxisAngle(const CVector3f& vec); static const CAxisAngle& Identity(); + + float GetAngle() const; const CVector3f& GetVector() const; const CAxisAngle& operator+=(const CAxisAngle& rhs); diff --git a/include/MetroidPrime/Cameras/CCameraManager.hpp b/include/MetroidPrime/Cameras/CCameraManager.hpp index b5d724f5..f5ac8876 100644 --- a/include/MetroidPrime/Cameras/CCameraManager.hpp +++ b/include/MetroidPrime/Cameras/CCameraManager.hpp @@ -26,8 +26,8 @@ public: const CGameCamera* GetCurrentCamera(const CStateManager& mgr) const; const CFirstPersonCamera* GetFirstPersonCamera() const { return x7c_fpCamera; } void SetPlayerCamera(CStateManager& mgr, TUniqueId newCamId); - void SetFogDensity(float fogDensityTarget, float fogDensitySpeed); + bool IsInCinematicCamera() const; static f32 DefaultThirdPersonFov(); diff --git a/include/MetroidPrime/Player/CGrappleArm.hpp b/include/MetroidPrime/Player/CGrappleArm.hpp index 7457a144..c8b91bd3 100644 --- a/include/MetroidPrime/Player/CGrappleArm.hpp +++ b/include/MetroidPrime/Player/CGrappleArm.hpp @@ -11,8 +11,14 @@ public: ~CGrappleArm(); void PreRender(CStateManager& mgr, const CFrustumPlanes& frustum, const CVector3f& camPos); + void ReturnToDefault(CStateManager& mgr, float dt, bool setState); + // EArmState GetAnimState() const { return x334_animState; } bool GetActive() const { return x3b2_24_active; } + bool BeamActive() const { return x3b2_25_beamActive; } + bool IsArmMoving() const { return x3b2_27_armMoving; } + bool IsGrappling() const { return x3b2_28_isGrappling; } + bool IsSuitLoading() const { return x3b2_29_suitLoading; } private: u8 x0_pad[0x3b0]; diff --git a/include/MetroidPrime/Player/CPlayer.hpp b/include/MetroidPrime/Player/CPlayer.hpp index a3cdc0ed..3163ad14 100644 --- a/include/MetroidPrime/Player/CPlayer.hpp +++ b/include/MetroidPrime/Player/CPlayer.hpp @@ -167,12 +167,21 @@ public: CPlayerGun* PlayerGun() { return x490_gun.get(); } const CPlayerGun* GetPlayerGun() const { return x490_gun.get(); } + + ESurfaceRestraints GetCurrentSurfaceRestraint() const { return x2ac_surfaceRestraint; } + ESurfaceRestraints GetSurfaceRestraint() const { + return x2b0_outOfWaterTicks == 2 ? GetCurrentSurfaceRestraint() : kSR_Water; + } TUniqueId GetOrbitTargetId() const { return x310_orbitTargetId; } TUniqueId GetOrbitNextTargetId() const { return x33c_orbitNextTargetId; } TUniqueId GetScanningObjectId() const { return x3b4_scanningObject; } EGrappleState GetGrappleState() const { return x3b8_grappleState; } + bool IsInFreeLook() const { return x3dc_inFreeLook; } + bool GetFreeLookStickState() const { return x3de_lookAnalogHeld; } + EPlayerCameraState GetCameraState() const { return x2f4_cameraState; } EGunHolsterState GetGunHolsterState() const { return x498_gunHolsterState; } + NPlayer::EPlayerMovementState GetPlayerMovementState() const { return x258_movementState; } private: struct CVisorSteam { diff --git a/include/MetroidPrime/Player/CPlayerGun.hpp b/include/MetroidPrime/Player/CPlayerGun.hpp index 68104e8f..64b0a1be 100644 --- a/include/MetroidPrime/Player/CPlayerGun.hpp +++ b/include/MetroidPrime/Player/CPlayerGun.hpp @@ -165,7 +165,7 @@ public: void ProcessGunMorph(float, CStateManager&); void AsyncLoadFidget(CStateManager&); void UnLoadFidget(); - void IsFidgetLoaded(); + bool IsFidgetLoaded(); void SetFidgetAnimBits(int, bool); void AsyncLoadSuit(CStateManager&); void ReturnToRestPose(); diff --git a/include/MetroidPrime/Weapons/CGunWeapon.hpp b/include/MetroidPrime/Weapons/CGunWeapon.hpp index 605b0bc8..83a25d2c 100644 --- a/include/MetroidPrime/Weapons/CGunWeapon.hpp +++ b/include/MetroidPrime/Weapons/CGunWeapon.hpp @@ -80,6 +80,7 @@ public: const CVelocityInfo& GetVelocityInfo() const { return x1d0_velInfo; } rstl::optional_object< CModelData >& SolidModelData() { return x10_solidModelData; } + const CModelData& GetSolidModelData() const { return x10_solidModelData.data(); } CAABox GetBounds() const; CAABox GetBounds(const CTransform4f& xf) const; diff --git a/include/MetroidPrime/Weapons/GunController/CGunMotion.hpp b/include/MetroidPrime/Weapons/GunController/CGunMotion.hpp index 6a135bce..ad565e38 100644 --- a/include/MetroidPrime/Weapons/GunController/CGunMotion.hpp +++ b/include/MetroidPrime/Weapons/GunController/CGunMotion.hpp @@ -4,14 +4,26 @@ #include "Kyoto/CObjectReference.hpp" class CVector3f; +class CStateManager; class CGunMotion { public: CGunMotion(CAssetId ancsId, const CVector3f& scale); ~CGunMotion(); + bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle, bool bigStrike); + void BasePosition(bool bigStrikeReset); + void ReturnToDefault(CStateManager& mgr, bool setState); + + CModelData& GetModelData() { return x0_modelData; } + const CModelData& GetModelData() const { return x0_modelData; } + bool IsAnimPlaying() const { return xb8_24_animPlaying; } + private: - u8 x0_pad[0xbc]; + CModelData x0_modelData; + u8 x4c_pad[0x5C]; + rstl::vector xa8_anims; + bool xb8_24_animPlaying : 1; }; CHECK_SIZEOF(CGunMotion, 0xbc) diff --git a/src/MetroidPrime/Player/CPlayerGun.cpp b/src/MetroidPrime/Player/CPlayerGun.cpp index b431af6b..ae457b08 100644 --- a/src/MetroidPrime/Player/CPlayerGun.cpp +++ b/src/MetroidPrime/Player/CPlayerGun.cpp @@ -6,6 +6,7 @@ #include "MetroidPrime/CStateManager.hpp" #include "MetroidPrime/CWorld.hpp" #include "MetroidPrime/CWorldShadow.hpp" +#include "MetroidPrime/Cameras/CCameraManager.hpp" #include "MetroidPrime/Player/CGrappleArm.hpp" #include "MetroidPrime/Player/CPlayer.hpp" #include "MetroidPrime/Tweaks/CTweakGunRes.hpp" @@ -32,6 +33,8 @@ #include "MetaRender/CCubeRenderer.hpp" +#include "math.h" + static float kVerticalAngleTable[3] = {-30.f, 0.f, 30.f}; static float kHorizontalAngleTable[3] = {30.f, 30.f, 30.f}; static float kVerticalVarianceTable[3] = {30.f, 30.f, 30.f}; @@ -792,7 +795,117 @@ void CPlayerGun::ResetIdle(CStateManager& mgr) { x834_26_animPlaying = false; } -void CPlayerGun::UpdateGunIdle(bool, float, float, CStateManager&) {} +void CPlayerGun::UpdateGunIdle(bool inStrikeCooldown, float camBobT, float dt, CStateManager& mgr) { + CPlayer& player = *mgr.Player(); + if (player.IsInFreeLook() && !x832_29_lockedOn && !x740_grappleArm->IsGrappling() && + x3a4_fidget.GetState() != CFidget::kS_HolsterBeam && + player.GetGunHolsterState() == CPlayer::kGH_Drawn && !x834_30_inBigStrike) { + if ((x2f8_stateFlags & 0x8) != 0x8) { + if (!x833_31_inFreeLook && !x834_26_animPlaying) { + if (x388_enterFreeLookDelayTimer < 0.25f) + x388_enterFreeLookDelayTimer += dt; + if (x388_enterFreeLookDelayTimer >= 0.25f && !x740_grappleArm->IsSuitLoading()) { + EnterFreeLook(mgr); + x833_31_inFreeLook = true; + } + } else { + x388_enterFreeLookDelayTimer = 0.f; + if (x834_26_animPlaying) + ResetIdle(mgr); + } + } + } else { + if (x833_31_inFreeLook) { + if ((x2f8_stateFlags & 0x10) != 0x10) { + x73c_gunMotion->ReturnToDefault(mgr, x834_30_inBigStrike); + x740_grappleArm->ReturnToDefault(mgr, 0.f, false); + } + x833_31_inFreeLook = false; + } + x388_enterFreeLookDelayTimer = 0.f; + if (player.GetMorphballTransitionState() != CPlayer::kMS_Morphed) { + x833_24_notFidgeting = + !(player.GetSurfaceRestraint() != CPlayer::kSR_Water && + mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::kPV_Scan && + (x2f4_fireButtonStates & 0x3) == 0 && x32c_chargePhase == kCP_NotCharging && !x832_29_lockedOn && + (x2f8_stateFlags & 0x8) != 0x8 && x364_gunStrikeCoolTimer <= 0.f && + player.GetPlayerMovementState() == NPlayer::kMS_OnGround && !player.IsInFreeLook() && + !player.GetFreeLookStickState() && player.GetOrbitState() == CPlayer::kOS_NoOrbit && + fabs(player.GetAngularVelocityOR().GetAngle()) <= 0.1f && camBobT <= 0.01f && + !mgr.GetCameraManager()->IsInCinematicCamera() && + player.GetGunHolsterState() == CPlayer::kGH_Drawn && + player.GetGrappleState() == CPlayer::kGS_None && !x834_30_inBigStrike && !x835_25_inPhazonBeam); + if (x833_24_notFidgeting) { + if (!x834_30_inBigStrike) { + bool doWander = camBobT > 0.01f && (x2f4_fireButtonStates & 0x3) == 0; + if (doWander) { + x370_gunMotionSpeedMult = 1.f; + x374_ = 0.f; + if (x364_gunStrikeCoolTimer <= 0.f && x368_idleWanderDelayTimer <= 0.f) { + x368_idleWanderDelayTimer = 8.f; + x73c_gunMotion->PlayPasAnim(SamusGun::kAS_Wander, mgr, 0.f, false); + x324_idleState = kIS_Wander; + x550_camBob.SetState(CPlayerCameraBob::kCBS_Walk, mgr); + } + x368_idleWanderDelayTimer -= dt; + x360_ -= dt; + } + if (!doWander || x834_26_animPlaying) + ResetIdle(mgr); + } else if (x394_damageTimer > 0.f) { + x394_damageTimer -= dt; + } else if (!x834_31_gunMotionInFidgetBasePosition) { + x394_damageTimer = 0.f; + x834_31_gunMotionInFidgetBasePosition = true; + x73c_gunMotion->BasePosition(true); + } else if (!x73c_gunMotion->GetModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, rstl::string_l("Whole Body"))) { + x834_30_inBigStrike = false; + x834_31_gunMotionInFidgetBasePosition = false; + } + } else { + switch (x3a4_fidget.Update(x2ec_lastFireButtonStates, camBobT > 0.01f, inStrikeCooldown, dt, mgr)) { + case CFidget::kS_NoFidget: + if (x324_idleState != kIS_Idle) { + x73c_gunMotion->PlayPasAnim(SamusGun::kAS_Idle, mgr, 0.f, false); + x324_idleState = kIS_Idle; + } + x550_camBob.SetState(CPlayerCameraBob::kCBS_WalkNoBob, mgr); + break; + case CFidget::kS_MinorFidget: + case CFidget::kS_MajorFidget: + case CFidget::kS_HolsterBeam: + if (x324_idleState != kIS_NotIdle) { + x73c_gunMotion->BasePosition(false); + x324_idleState = kIS_NotIdle; + } + AsyncLoadFidget(mgr); + break; + case CFidget::kS_Loading: + if (IsFidgetLoaded()) + EnterFidget(mgr); + break; + case CFidget::kS_StillMinorFidget: + case CFidget::kS_StillMajorFidget: + x550_camBob.SetState(CPlayerCameraBob::kCBS_Walk, mgr); + x833_24_notFidgeting = false; + x834_26_animPlaying = + x834_25_gunMotionFidgeting + ? x73c_gunMotion->IsAnimPlaying() + : x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, rstl::string_l("Whole Body")); + if (!x834_26_animPlaying) { + x3a4_fidget.ResetMinor(); + ReturnToRestPose(); + } + break; + default: + break; + } + } + x550_camBob.Update(dt, mgr); + } + } +} + void CPlayerGun::CMotionState::Update(bool, float, CTransform4f&, CStateManager&) {} @@ -846,7 +959,9 @@ void CPlayerGun::AsyncLoadFidget(CStateManager&) {} void CPlayerGun::UnLoadFidget() {} -void CPlayerGun::IsFidgetLoaded() {} +bool CPlayerGun::IsFidgetLoaded() { + return false; +} void CPlayerGun::SetFidgetAnimBits(int, bool) {}