diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index 036a99f2d..a70a730cc 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -15,8 +15,9 @@ class CPlayerState { friend class CWorldTransManager; public: - enum class EItemType : u32 + enum class EItemType : s32 { + Invalid = -1, PowerBeam = 0, IceBeam = 1, WaveBeam = 2, @@ -127,7 +128,7 @@ public: float sub_80091204() const; u32 GetMissileCostForAltAttack() const; - static float GetMissileComboChargeFactor() { return 1.8f; } + static constexpr float GetMissileComboChargeFactor() { return 1.8f; } u32 CalculateItemCollectionRate() const; CHealthInfo& HealthInfo(); diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 4a5e60d89..4f16bffbd 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -85,6 +85,7 @@ class CAnimData { friend class CModelData; friend class CActor; + friend class CPlayerGun; public: enum class EAnimDir { diff --git a/Runtime/Input/CRumbleManager.hpp b/Runtime/Input/CRumbleManager.hpp index db706f2b1..598b79d47 100644 --- a/Runtime/Input/CRumbleManager.hpp +++ b/Runtime/Input/CRumbleManager.hpp @@ -17,7 +17,7 @@ public: void Update(float); void StopRumble(s16) {} void Rumble(CStateManager&, ERumbleFxId, ERumblePriority priority) {} - void Rumble(CStateManager&, ERumbleFxId, float, ERumblePriority priority) {} + s16 Rumble(CStateManager&, ERumbleFxId, float, ERumblePriority priority) {return 0;} }; } diff --git a/Runtime/Input/CRumbleVoice.hpp b/Runtime/Input/CRumbleVoice.hpp index 30c52a6ba..0969d55ed 100644 --- a/Runtime/Input/CRumbleVoice.hpp +++ b/Runtime/Input/CRumbleVoice.hpp @@ -9,13 +9,15 @@ enum class ERumbleFxId { Seven = 7, Eleven = 11, + Twelve = 12, Fifteen = 15 }; enum class ERumblePriority { None = 0, One = 1, - Two = 2 + Two = 2, + Three = 3 }; struct SAdsrData; diff --git a/Runtime/Weapon/CAuxWeapon.cpp b/Runtime/Weapon/CAuxWeapon.cpp index b0d95fde3..5f203cd1b 100644 --- a/Runtime/Weapon/CAuxWeapon.cpp +++ b/Runtime/Weapon/CAuxWeapon.cpp @@ -28,6 +28,18 @@ void CAuxWeapon::StopComboFx(CStateManager& mgr, bool b1) } +bool CAuxWeapon::UpdateComboFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, + const zeus::CTransform& xf, CStateManager& mgr) +{ + return false; +} + +void CAuxWeapon::Fire(bool underwater, CPlayerState::EBeamId currentBeam, EChargeState chargeState, + const zeus::CTransform& xf, CStateManager& mgr, EWeaponType type, TUniqueId homingId) +{ + +} + void CAuxWeapon::LoadIdle() { @@ -38,4 +50,14 @@ void CAuxWeapon::RenderMuzzleFx() const } +TUniqueId CAuxWeapon::HasTarget(const CStateManager& mgr) const +{ + return {}; +} + +void CAuxWeapon::SetNewTarget(TUniqueId targetId, CStateManager& mgr) +{ + +} + } diff --git a/Runtime/Weapon/CAuxWeapon.hpp b/Runtime/Weapon/CAuxWeapon.hpp index 7d5bdd709..1c2a8e823 100644 --- a/Runtime/Weapon/CAuxWeapon.hpp +++ b/Runtime/Weapon/CAuxWeapon.hpp @@ -4,6 +4,7 @@ #include "CPlayerState.hpp" #include "RetroTypes.hpp" #include "CStateManager.hpp" +#include "CGunWeapon.hpp" namespace urde { @@ -17,9 +18,15 @@ public: bool IsComboFxActive(const CStateManager& mgr) const; void Load(CPlayerState::EBeamId curBeam, CStateManager& mgr); void StopComboFx(CStateManager& mgr, bool b1); + bool UpdateComboFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, + const zeus::CTransform& xf, CStateManager& mgr); + void Fire(bool underwater, CPlayerState::EBeamId currentBeam, EChargeState chargeState, + const zeus::CTransform& xf, CStateManager& mgr, EWeaponType type, TUniqueId homingId); void LoadIdle(); bool IsLoaded() const { return x80_24_isLoaded; } void RenderMuzzleFx() const; + TUniqueId HasTarget(const CStateManager& mgr) const; + void SetNewTarget(TUniqueId targetId, CStateManager& mgr); }; } diff --git a/Runtime/Weapon/CFidget.cpp b/Runtime/Weapon/CFidget.cpp index cce23f652..dd2def5ca 100644 --- a/Runtime/Weapon/CFidget.cpp +++ b/Runtime/Weapon/CFidget.cpp @@ -3,7 +3,7 @@ namespace urde { -CFidget::EState CFidget::Update(int fire, bool bobbing, bool b1, float dt, CStateManager& mgr) +CFidget::EState CFidget::Update(int fire, bool bobbing, bool inStrikeCooldown, float dt, CStateManager& mgr) { return EState::Zero; } diff --git a/Runtime/Weapon/CFidget.hpp b/Runtime/Weapon/CFidget.hpp index 5d543dca9..3391181bc 100644 --- a/Runtime/Weapon/CFidget.hpp +++ b/Runtime/Weapon/CFidget.hpp @@ -41,7 +41,7 @@ public: EState GetState() const { return x0_state; } SamusGun::EFidgetType GetType() const { return x4_type; } s32 GetParm2() const { return xc_parm2; } - EState Update(int fire, bool bobbing, bool b1, float dt, CStateManager& mgr); + EState Update(int fire, bool bobbing, bool inStrikeCooldown, float dt, CStateManager& mgr); void ResetMinor(); void ResetAll(); void DoneLoading() { x34_24_loading = false; } diff --git a/Runtime/Weapon/CGrappleArm.cpp b/Runtime/Weapon/CGrappleArm.cpp index 536ce90a5..78395c1f3 100644 --- a/Runtime/Weapon/CGrappleArm.cpp +++ b/Runtime/Weapon/CGrappleArm.cpp @@ -82,6 +82,11 @@ void CGrappleArm::EnterFreeLook(s32 gunId, s32 setId, CStateManager& mgr) } +void CGrappleArm::EnterComboFire(s32 gunId, CStateManager& mgr) +{ + +} + void CGrappleArm::ReturnToDefault(CStateManager& mgr, float f1, bool b1) { diff --git a/Runtime/Weapon/CGrappleArm.hpp b/Runtime/Weapon/CGrappleArm.hpp index 52459dc60..166ae27cc 100644 --- a/Runtime/Weapon/CGrappleArm.hpp +++ b/Runtime/Weapon/CGrappleArm.hpp @@ -77,6 +77,7 @@ public: void EnterIdle(CStateManager& mgr); void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 gunId, s32 parm2); void EnterFreeLook(s32 gunId, s32 setId, CStateManager& mgr); + void EnterComboFire(s32 gunId, CStateManager& mgr); void ReturnToDefault(CStateManager& mgr, float f1, bool b1); CGunController* GunController() { return x328_gunController.get(); } }; diff --git a/Runtime/Weapon/CGunWeapon.cpp b/Runtime/Weapon/CGunWeapon.cpp index cf06a707c..2c89cb795 100644 --- a/Runtime/Weapon/CGunWeapon.cpp +++ b/Runtime/Weapon/CGunWeapon.cpp @@ -1,6 +1,7 @@ #include "CGunWeapon.hpp" #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" +#include "Character/CModelData.hpp" namespace urde { @@ -55,6 +56,24 @@ void CGunWeapon::AsyncLoadSuitArm(CStateManager& mgr) { } +void CGunWeapon::AllocResPools(CPlayerState::EBeamId) +{ + +} + +static const s32 skAnimTypeList[] = { 0, 4, 1, 2, 3, 5, 6, 7, 8, 9, 10 }; + +void CGunWeapon::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) +{ + if (x218_26 && type >= NWeaponTypes::EGunAnimType::BasePosition && + type <= NWeaponTypes::EGunAnimType::ToBeam) + { + x10_solidModelData->AnimationData()->EnableLooping(loop); + CAnimPlaybackParms parms(skAnimTypeList[int(type)], -1, 1.f, true); + x10_solidModelData->AnimationData()->SetAnimation(parms, false); + } +} + void CGunWeapon::BuildSecondaryEffect(ESecondaryFxType type) { switch (type) @@ -124,4 +143,9 @@ zeus::CAABox CGunWeapon::GetBounds(const zeus::CTransform& xf) const return zeus::CAABox::skNullBox; } +bool CGunWeapon::IsChargeAnimOver() const +{ + return false; +} + } diff --git a/Runtime/Weapon/CGunWeapon.hpp b/Runtime/Weapon/CGunWeapon.hpp index c146d0342..c1802dd4b 100644 --- a/Runtime/Weapon/CGunWeapon.hpp +++ b/Runtime/Weapon/CGunWeapon.hpp @@ -63,7 +63,7 @@ protected: TToken x104_gunCharacter; TToken x13c_armCharacter; rstl::reserved_vector, 2> x144_weapons; - TToken x160_xferEffect; + TCachedToken x160_xferEffect; rstl::reserved_vector, 2> x16c_muzzleEffects; rstl::reserved_vector, 2> x188_secondaryEffects; rstl::reserved_vector, 2> x1a4_muzzleGenerators; @@ -84,7 +84,7 @@ protected: struct { bool x218_24 : 1; - bool x218_25 : 1; + bool x218_25_enableCharge : 1; bool x218_26 : 1; bool x218_27 : 1; bool x218_28 : 1; @@ -97,12 +97,11 @@ public: CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes, const zeus::CVector3f& scale); void AsyncLoadSuitArm(CStateManager& mgr); void AllocResPools(CPlayerState::EBeamId); - virtual void Reset(CStateManager&) {} - virtual void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) {} + virtual void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop); virtual void PreRenderGunFx(const CStateManager&, const zeus::CTransform&) {} virtual void PostRenderGunFx(const CStateManager&, const zeus::CTransform&) {} - virtual void UpdateGunFx(bool, float, const CStateManager&, const zeus::CTransform&) {} + virtual void UpdateGunFx(bool shotSmoke, float, const CStateManager&, const zeus::CTransform&) {} virtual void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, TUniqueId homingTarget) {} virtual void EnableFx(bool) {} @@ -123,7 +122,9 @@ public: const CVelocityInfo& GetVelocityInfo() const { return x1d0_velInfo; } void SetRainSplashGenerator(CRainSplashGenerator* g) { x1bc_rainSplashGenerator = g; } CElementGen* GetChargeMuzzleFx() const { return x1a4_muzzleGenerators[1].get(); } + const TToken& GetComboXferDescr() const { return x160_xferEffect; } void ReturnToDefault(CStateManager& mgr) {} + bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle) { return false; } void UnLoadFidget() {} bool IsFidgetLoaded() const { return x100_gunController->IsFidgetLoaded(); } void AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) @@ -133,9 +134,13 @@ public: bool HasSolidModelData() const { return x10_solidModelData.operator bool(); } CModelData& GetSolidModelData() { return *x10_solidModelData; } const SWeaponInfo& GetWeaponInfo() const; + EWeaponType GetWeaponType() const { return x1c0_weaponType; } zeus::CAABox GetBounds() const; zeus::CAABox GetBounds(const zeus::CTransform& xf) const; + bool ComboFireOver() const { return x100_gunController->IsComboOver(); } + bool IsChargeAnimOver() const; void SetLeavingBeam(bool leaving) { x218_29_leavingBeam = leaving; } + void EnableCharge(bool c) { x218_25_enableCharge = c; } }; } diff --git a/Runtime/Weapon/CPhazonBeam.cpp b/Runtime/Weapon/CPhazonBeam.cpp index 828b87b7f..dbcab63d7 100644 --- a/Runtime/Weapon/CPhazonBeam.cpp +++ b/Runtime/Weapon/CPhazonBeam.cpp @@ -31,4 +31,10 @@ void CPhazonBeam::StopBeam(CStateManager& mgr, bool b1) } +void CPhazonBeam::UpdateBeam(float dt, const zeus::CTransform& targetXf, + const zeus::CVector3f& localBeamPos, CStateManager& mgr) +{ + +} + } \ No newline at end of file diff --git a/Runtime/Weapon/CPhazonBeam.hpp b/Runtime/Weapon/CPhazonBeam.hpp index 94004db0a..31f97a453 100644 --- a/Runtime/Weapon/CPhazonBeam.hpp +++ b/Runtime/Weapon/CPhazonBeam.hpp @@ -29,6 +29,8 @@ public: void SetX274_25(bool b) { x274_25 = b; } void SetX274_26(bool b) { x274_26 = b; } void StopBeam(CStateManager& mgr, bool b1); + void UpdateBeam(float dt, const zeus::CTransform& targetXf, + const zeus::CVector3f& localBeamPos, CStateManager& mgr); }; } diff --git a/Runtime/Weapon/CPlasmaBeam.hpp b/Runtime/Weapon/CPlasmaBeam.hpp index c23332e35..a08dd9dd8 100644 --- a/Runtime/Weapon/CPlasmaBeam.hpp +++ b/Runtime/Weapon/CPlasmaBeam.hpp @@ -22,6 +22,8 @@ public: void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); bool IsFiring() const { return x234_ > 0.f; } void StopBeam(CStateManager& mgr, bool b1) {} + void UpdateBeam(float dt, const zeus::CTransform& targetXf, + const zeus::CVector3f& localBeamPos, CStateManager& mgr) {} }; } diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index 4959f93cf..a93bad19a 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -1,13 +1,8 @@ #include #include -#include "TCastTo.hpp" -#include "CPlayerGun.hpp" -#include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" #include "Character/CPrimitive.hpp" -#include "World/CPlayer.hpp" #include "CEnergyProjectile.hpp" -#include "MP1/World/CMetroid.hpp" #include "World/CScriptWater.hpp" #include "World/CGameLight.hpp" #include "World/CScriptPlatform.hpp" @@ -15,9 +10,7 @@ #include "CBomb.hpp" #include "CPowerBomb.hpp" #include "Graphics/CBooRenderer.hpp" -#include "World/CWorld.hpp" #include "Camera/CGameCamera.hpp" -#include "GuiSys/CStringTable.hpp" namespace urde { @@ -64,9 +57,9 @@ CPlayerGun::CPlayerGun(TUniqueId playerId) CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One); x82c_shadow = std::make_unique(32, 32, true); - x832_31_ = true; + x832_31_inRestPose = true; x833_24_isFidgeting = true; - x833_30_ = true; + x833_30_canShowAuxMuzzleEffect = true; x6e0_rightHandModel.SetSortThermal(true); kVerticalAngleTable[2] = g_tweakPlayerGun->GetUpLookAngle(); @@ -126,7 +119,7 @@ void CPlayerGun::InitMuzzleData() void CPlayerGun::InitCTData() { - x77c_.reset(); + x77c_comboXferGen.reset(); } void CPlayerGun::LoadHandAnimTokens() @@ -142,27 +135,28 @@ void CPlayerGun::LoadHandAnimTokens() void CPlayerGun::TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr) { - bool hasAngle = false; + bool hasStrikeAngle = false; float angle = 0.f; - if (x398_damageAmt >= 10.f && !bigStrike && (x2f8_ & 0x10) != 0x10 && !x832_26_ && x384_ <= 0.f) + if (x398_damageAmt >= 10.f && !bigStrike && (x2f8_stateFlags & 0x10) != 0x10 && + !x832_26_comboFiring && x384_gunStrikeDelayTimer <= 0.f) { - x384_ = 20.f; - x364_ = 0.75f; + x384_gunStrikeDelayTimer = 20.f; + x364_gunStrikeCoolTimer = 0.75f; if (x678_morph.GetGunState() == CGunMorph::EGunState::OutWipeDone) { zeus::CVector3f localDamageLoc = mgr.GetPlayer().GetTransform().transposeRotate(x3dc_damageLocation); angle = zeus::CRelAngle(std::atan2(localDamageLoc.y, localDamageLoc.x)).asDegrees(); - hasAngle = true; + hasStrikeAngle = true; } } - if (hasAngle || bigStrike) + if (hasStrikeAngle || bigStrike) { if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Struck, mgr, angle, bigStrike); - if ((bigStrike && notFromMetroid) || x833_31_) - x740_grappleArm->EnterStruck(mgr, angle, bigStrike, !x833_31_); + if ((bigStrike && notFromMetroid) || x833_31_inFreeLook) + x740_grappleArm->EnterStruck(mgr, angle, bigStrike, !x833_31_inFreeLook); } } @@ -189,9 +183,26 @@ void CPlayerGun::DeleteGunLight(CStateManager& mgr) x53c_lightId = kInvalidUniqueId; } -void CPlayerGun::UpdateGunLight(const zeus::CTransform& pos, CStateManager& mgr) +void CPlayerGun::UpdateGunLight(const zeus::CTransform& xf, CStateManager& mgr) { + if (x53c_lightId == kInvalidUniqueId || x32c_chargePhase == EChargePhase::NotCharging) + return; + if (TCastToPtr light = mgr.ObjectById(x53c_lightId)) + { + if (light->GetActive()) + { + CElementGen* chargeFx = x72c_currentBeam->GetChargeMuzzleFx(); + light->SetTransform(xf); + light->SetTranslation(xf.origin); + if (chargeFx && chargeFx->SystemHasLight()) + { + CLight l = chargeFx->GetLight(); + l.SetColor(zeus::CColor::lerp(zeus::CColor::skClear, l.GetColor(), x340_chargeBeamFactor)); + light->SetLight(l); + } + } + } } void CPlayerGun::SetGunLightActive(bool active, CStateManager& mgr) @@ -315,7 +326,7 @@ void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt { if (bigStrike) { - x834_31_ = false; + x834_31_gunMotionInFidgetBasePosition = false; CancelFiring(mgr); } TakeDamage(bigStrike, !metroidAttached, mgr); @@ -355,13 +366,13 @@ void CPlayerGun::TouchModel(const CStateManager& mgr) if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { x73c_gunMotion->GetModelData().Touch(mgr, 0); - switch (x33c_gunOverrideMode) + switch (x33c_phazonBeamState) { - case EGunOverrideMode::One: + case EPhazonBeamState::Entering: if (x75c_phazonBeam) x75c_phazonBeam->Touch(mgr); break; - case EGunOverrideMode::Two: + case EPhazonBeamState::Exiting: if (x738_nextBeam) x738_nextBeam->Touch(mgr); break; @@ -406,44 +417,44 @@ void CPlayerGun::StopChargeSound(CStateManager& mgr) void CPlayerGun::ResetCharge(CStateManager& mgr, bool b1) { - if (x32c_) + if (x32c_chargePhase != EChargePhase::NotCharging) StopChargeSound(mgr); - if ((x2f8_ & 0x8) != 0x8 && (x2f8_ & 0x10) != 0x10) + if ((x2f8_stateFlags & 0x8) != 0x8 && (x2f8_stateFlags & 0x10) != 0x10) { bool r30 = !(mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed && !b1); - if (x832_27_ || r30) - PlayAnim(NWeaponTypes::EGunAnimType::Zero, false); + if (x832_27_chargeAnimStarted || r30) + PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); if (r30) x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero); - if ((x2f8_ & 0x2) != 0x2 || x330_chargeState != EChargeState::Normal) + if ((x2f8_stateFlags & 0x2) != 0x2 || x330_chargeState != EChargeState::Normal) { - if ((x2f8_ & 0x8) != 0x8) + if ((x2f8_stateFlags & 0x8) != 0x8) { - x2f8_ |= 0x1; - x2f8_ &= 0xFFE9; + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; } - x318_ = 0; + x318_comboAmmoIdx = 0; x31c_missileMode = EMissleMode::Inactive; } } - x32c_ = 0; + x32c_chargePhase = EChargePhase::NotCharging; x330_chargeState = EChargeState::Normal; x320_currentAuxBeam = x310_currentBeam; - x833_30_ = true; - x832_27_ = false; - x832_26_ = false; - x344_ = 0.f; + x833_30_canShowAuxMuzzleEffect = true; + x832_27_chargeAnimStarted = false; + x832_26_comboFiring = false; + x344_comboXferTimer = 0.f; } bool CPlayerGun::ExitMissile() { - if ((x2f8_ & 0x1) == 0x1) + if ((x2f8_stateFlags & 0x1) == 0x1) return true; - if ((x2f8_ & 0x10) == 0x10 || x338_ == 2) + if ((x2f8_stateFlags & 0x10) == 0x10 || x338_nextState == ENextState::ExitMissile) return false; - x338_ = 2; + x338_nextState = ENextState::ExitMissile; PlayAnim(NWeaponTypes::EGunAnimType::FromMissile, false); return false; } @@ -498,18 +509,18 @@ void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr) { x314_nextBeam = selectBeam; u32 flags = 0; - if ((x2f8_ & 0x10) == 0x10) + if ((x2f8_stateFlags & 0x10) == 0x10) flags = 0x10; flags |= 0x8; - x2f8_ = flags; + x2f8_stateFlags = flags; PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false); - if (x833_31_ || x744_auxWeapon->IsComboFxActive(mgr) || x832_26_) + if (x833_31_inFreeLook || x744_auxWeapon->IsComboFxActive(mgr) || x832_26_comboFiring) { - x832_30_ = true; + x832_30_requestReturnToDefault = true; x740_grappleArm->EnterIdle(mgr); } x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero); - x338_ = 5; + x338_nextState = ENextState::ChangeWeapon; x2e4_invalidSfx.reset(); } else if (playerState.HasPowerUp(skBeamArr[int(selectBeam)])) @@ -536,27 +547,27 @@ void CPlayerGun::SetPhazonBeamMorph(bool intoPhazonBeam) void CPlayerGun::Reset(CStateManager& mgr, bool b1) { x72c_currentBeam->Reset(mgr); - x832_25_ = false; - x832_24_ = false; + x832_25_chargeEffectVisible = false; + x832_24_cancellingCharge = false; x833_26_ = false; - x348_ = 0.f; + x348_chargeCancelTimer = 0.f; SetGunLightActive(false, mgr); - if ((x2f8_ & 0x10) != 0x10) + if ((x2f8_stateFlags & 0x10) != 0x10) { - if (!b1 && (x2f8_ & 0x2) != 0x2) + if (!b1 && (x2f8_stateFlags & 0x2) != 0x2) { - if ((x2f8_ & 0x8) != 0x8) + if ((x2f8_stateFlags & 0x8) != 0x8) { - x2f8_ |= 0x1; - x2f8_ &= 0xFFE9; + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; } - x318_ = 0; + x318_comboAmmoIdx = 0; x31c_missileMode = EMissleMode::Inactive; } } else { - x2f8_ &= ~0x7; + x2f8_stateFlags &= ~0x7; } } @@ -572,7 +583,7 @@ void CPlayerGun::ResetBeamParams(CStateManager& mgr, const CPlayerState& playerS CSfxManager::SfxStart(1774, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); x2ec_lastFireButtonStates &= ~0x1; x320_currentAuxBeam = x310_currentBeam; - x833_30_ = true; + x833_30_canShowAuxMuzzleEffect = true; } CSfxHandle CPlayerGun::PlaySfx(u16 sfx, bool underwater, bool looped, float pan) @@ -590,14 +601,14 @@ static const u16 skToMissileSound[] = { 1823, 1829, 1850, 1852 }; void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) { - if (x338_ != 5) + if (x338_nextState != ENextState::ChangeWeapon) x72c_currentBeam->PlayAnim(type, loop); u16 sfx = 0xffff; switch (type) { case NWeaponTypes::EGunAnimType::FromMissile: - x2f8_ &= ~0x4; + x2f8_stateFlags &= ~0x4; sfx = skFromMissileSound[int(x310_currentBeam)]; break; case NWeaponTypes::EGunAnimType::MissileReload: @@ -607,7 +618,7 @@ void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) sfx = skFromBeamSound[int(x310_currentBeam)]; break; case NWeaponTypes::EGunAnimType::ToMissile: - x2f8_ &= ~0x1; + x2f8_stateFlags &= ~0x1; sfx = skToMissileSound[int(x310_currentBeam)]; break; default: @@ -622,7 +633,7 @@ void CPlayerGun::CancelCharge(CStateManager& mgr, bool withEffect) { if (withEffect) { - x32c_ = 9; + x32c_chargePhase = EChargePhase::ChargeCancelled; x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Three); } else @@ -631,7 +642,7 @@ void CPlayerGun::CancelCharge(CStateManager& mgr, bool withEffect) } x834_24_charging = false; - x348_ = 0.f; + x348_chargeCancelTimer = 0.f; x72c_currentBeam->ActivateCharge(false, false); SetGunLightActive(false, mgr); } @@ -639,18 +650,18 @@ void CPlayerGun::CancelCharge(CStateManager& mgr, bool withEffect) void CPlayerGun::HandlePhazonBeamChange(CStateManager& mgr) { bool inMorph = false; - switch (x33c_gunOverrideMode) + switch (x33c_phazonBeamState) { - case EGunOverrideMode::Normal: + case EPhazonBeamState::Inactive: SetPhazonBeamMorph(true); - x338_ = 8; + x338_nextState = ENextState::EnterPhazonBeam; inMorph = true; break; - case EGunOverrideMode::Three: + case EPhazonBeamState::Active: if (!x835_25_inPhazonBeam) { SetPhazonBeamMorph(true); - x338_ = 9; + x338_nextState = ENextState::ExitPhazonBeam; inMorph = true; if (x75c_phazonBeam) { @@ -666,11 +677,11 @@ void CPlayerGun::HandlePhazonBeamChange(CStateManager& mgr) if (inMorph) { ResetBeamParams(mgr, *mgr.GetPlayerState(), true); - x2f8_ = 0x8; + x2f8_stateFlags = 0x8; PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false); - if (x833_31_) + if (x833_31_inFreeLook) { - x832_30_ = true; + x832_30_requestReturnToDefault = true; x740_grappleArm->EnterIdle(mgr); } CancelCharge(mgr, false); @@ -682,7 +693,7 @@ void CPlayerGun::HandleWeaponChange(const CFinalInput& input, CStateManager& mgr x833_25_ = false; if (ControlMapper::GetPressInput(ControlMapper::ECommands::Morph, input)) StopContinuousBeam(mgr, true); - if ((x2f8_ & 0x8) != 0x8) + if ((x2f8_stateFlags & 0x8) != 0x8) { if (!x835_25_inPhazonBeam) HandleBeamChange(input, mgr); @@ -696,7 +707,7 @@ void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr) CPlayerState& state = *mgr.GetPlayerState(); bool damageNotMorphed = (x834_30_inBigStrike && mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed); - if (x832_24_ || damageNotMorphed || (x2f8_ & 0x8) == 0x8) + if (x832_24_cancellingCharge || damageNotMorphed || (x2f8_stateFlags & 0x8) == 0x8) return; if (state.HasPowerUp(CPlayerState::EItemType::ChargeBeam)) { @@ -714,7 +725,7 @@ void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr) x2f4_fireButtonStates = 0; break; case CPlayer::EPlayerMorphBallState::Unmorphed: - if ((x2f8_ & 0x10) != 0x10) + if ((x2f8_stateFlags & 0x10) != 0x10) HandleWeaponChange(input, mgr); case CPlayer::EPlayerMorphBallState::Morphed: x2f4_fireButtonStates = @@ -737,27 +748,27 @@ void CPlayerGun::UnLoadFidget() x2fc_fidgetAnimBits = 0; } -void CPlayerGun::ReturnArmAndGunToDefault(CStateManager& mgr, bool b1) +void CPlayerGun::ReturnArmAndGunToDefault(CStateManager& mgr, bool returnToDefault) { - if (b1 || !x833_31_) + if (returnToDefault || !x833_31_inFreeLook) { x73c_gunMotion->ReturnToDefault(mgr, false); x740_grappleArm->ReturnToDefault(mgr, 0.f, false); } - if (!x834_25_) + if (!x834_25_gunMotionFidgeting) x72c_currentBeam->ReturnToDefault(mgr); - x834_25_ = false; + x834_25_gunMotionFidgeting = false; } void CPlayerGun::ReturnToRestPose() { - if (x832_31_) + if (x832_31_inRestPose) return; - if ((x2f8_ & 0x1) == 0x1) - PlayAnim(NWeaponTypes::EGunAnimType::Zero, false); - else if ((x2f8_ & 0x4) == 0x4) + if ((x2f8_stateFlags & 0x1) == 0x1) + PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); + else if ((x2f8_stateFlags & 0x4) == 0x4) PlayAnim(NWeaponTypes::EGunAnimType::ToMissile, false); - x832_31_ = true; + x832_31_inRestPose = true; } void CPlayerGun::ResetIdle(CStateManager& mgr) @@ -771,34 +782,34 @@ void CPlayerGun::ResetIdle(CStateManager& mgr) } x3a4_fidget.ResetAll(); ReturnToRestPose(); - if (x324_ != 0) - x324_ = 0; + if (x324_idleState != EIdleState::NotIdle) + x324_idleState = EIdleState::NotIdle; if (!x740_grappleArm->GetActive()) - x834_26_ = false; + x834_26_animPlaying = false; } void CPlayerGun::CancelFiring(CStateManager& mgr) { - if (x32c_ == 8) + if (x32c_chargePhase == EChargePhase::ComboFireDone) ReturnArmAndGunToDefault(mgr, true); - if ((x2f8_ & 0x10) == 0x10) + if ((x2f8_stateFlags & 0x10) == 0x10) { StopContinuousBeam(mgr, true); - if ((x2f8_ & 0x8) == 0x8) + if ((x2f8_stateFlags & 0x8) == 0x8) { - x2f8_ |= 0x1; - x2f8_ &= 0xFFE9; + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; } - x318_ = 0; + x318_comboAmmoIdx = 0; x31c_missileMode = EMissleMode::Inactive; } - if (x32c_ != 0) + if (x32c_chargePhase != EChargePhase::NotCharging) { x72c_currentBeam->ActivateCharge(false, false); SetGunLightActive(false, mgr); ResetCharge(mgr, true); } - Reset(mgr, (x2f8_ & 0x2) == 0x2); + Reset(mgr, (x2f8_stateFlags & 0x2) == 0x2); } float CPlayerGun::GetBeamVelocity() const @@ -810,7 +821,7 @@ float CPlayerGun::GetBeamVelocity() const void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1) { - if ((x2f8_ & 0x10) == 0x10) + if ((x2f8_stateFlags & 0x10) == 0x10) { ReturnArmAndGunToDefault(mgr, false); x744_auxWeapon->StopComboFx(mgr, b1); @@ -842,9 +853,101 @@ void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1) } } -void CPlayerGun::CMotionState::Update(bool b1, float dt, zeus::CTransform& xf, CStateManager& mgr) +void CPlayerGun::CMotionState::Update(bool firing, float dt, zeus::CTransform& xf, CStateManager& mgr) { + if (firing) + { + x24_fireState = EFireState::StartFire; + x8_fireTime = 0.f; + } + else if (x24_fireState != EFireState::NotFiring) + { + if (x8_fireTime > dt) + x24_fireState = EFireState::Firing; + x8_fireTime += dt; + } + if (x0_24_extendParabola && x20_state == EMotionState::LockOn) + { + float extendT = xc_curExtendDist / gGunExtendDistance; + xf = xf * zeus::CTransform::RotateZ(zeus::degToRad(extendT * -4.f * (extendT - 1.f) * 15.f)); + } + else + { + if (x24_fireState == EFireState::StartFire || x24_fireState == EFireState::Firing) + { + if (std::fabs(x14_rotationT - 1.f) < 0.1f) + { + x18_startRotation = x1c_endRotation; + x14_rotationT = 0.f; + if (x24_fireState == EFireState::StartFire) + { + x1c_endRotation = mgr.GetActiveRandom()->Next() % 15; + x1c_endRotation *= (mgr.GetActiveRandom()->Next() % 100) > 45 ? 1.f : -1.f; + } + else + { + x1c_endRotation = 0.f; + if (x18_startRotation == x1c_endRotation) + { + x10_curRotation = x1c_endRotation; + x24_fireState = EFireState::NotFiring; + } + } + } + else + { + x10_curRotation = (x1c_endRotation - x18_startRotation) * x14_rotationT + x18_startRotation; + } + + x14_rotationT += (1.f - x14_rotationT) * 0.8f * (10.f * dt); + zeus::CTransform tmpXf = + zeus::CQuaternion::fromAxisAngle(xf.basis[1], zeus::degToRad(x10_curRotation)).toTransform() * + xf.getRotation(); + tmpXf.basis = xf.basis; + xf = tmpXf * zeus::CTransform::Translate(0.f, xc_curExtendDist, 0.f); + } + else + { + xf = xf * zeus::CTransform::Translate(0.f, xc_curExtendDist, 0.f); + } + } + + switch (x20_state) + { + case EMotionState::LockOn: + xc_curExtendDist += 3.f * dt; + if (xc_curExtendDist > gGunExtendDistance) + { + xc_curExtendDist = gGunExtendDistance; + x20_state = EMotionState::One; + x0_24_extendParabola = false; + } + break; + case EMotionState::CancelLockOn: + xc_curExtendDist -= 3.f * dt; + if (xc_curExtendDist < 0.f) + { + xc_curExtendDist = 0.f; + x20_state = EMotionState::Zero; + } + break; + default: + break; + } + + if (!x0_24_extendParabola) + { + if (x4_extendParabolaDelayTimer < 30.f) + { + x4_extendParabolaDelayTimer += dt; + } + else + { + x0_24_extendParabola = true; + x4_extendParabolaDelayTimer = 0.f; + } + } } void CPlayerGun::ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr) @@ -860,7 +963,7 @@ void CPlayerGun::ChangeWeapon(const CPlayerState& playerState, CStateManager& mg } x72c_currentBeam->EnableFx(false); - x834_28_ = x32c_ != 0; + x834_28_requestImmediateRecharge = x32c_chargePhase != EChargePhase::NotCharging; ResetBeamParams(mgr, playerState, true); x678_morph.StartWipe(CGunMorph::EDir::In); } @@ -879,7 +982,7 @@ void CPlayerGun::GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mDa void CPlayerGun::UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr) { - if (x834_26_) + if (x834_26_animPlaying) x740_grappleArm->AuxTransform() = zeus::CTransform::Identity(); else GetLctrWithShake(x740_grappleArm->AuxTransform(), mData, "elbow", true, false); @@ -984,7 +1087,7 @@ void CPlayerGun::ProcessGunMorph(float dt, CStateManager& mgr) x734_loadingBeam = nullptr; x310_currentBeam = x314_nextBeam; x320_currentAuxBeam = x314_nextBeam; - x833_30_ = true; + x833_30_canShowAuxMuzzleEffect = true; x72c_currentBeam = x760_selectableBeams[int(x314_nextBeam)]; x738_nextBeam = x72c_currentBeam; x678_morph.SetWeaponChanged(); @@ -1016,19 +1119,19 @@ void CPlayerGun::ProcessGunMorph(float dt, CStateManager& mgr) PlaySfx(skIntoBeamSound[int(x310_currentBeam)], x834_27_underwater, false, 0.165f); x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); x72c_currentBeam->EnableFx(true); - PlayAnim(NWeaponTypes::EGunAnimType::Ten, false); - if (x833_31_) + PlayAnim(NWeaponTypes::EGunAnimType::ToBeam, false); + if (x833_31_inFreeLook) EnterFreeLook(mgr); - else if (x832_30_) + else if (x832_30_requestReturnToDefault) ReturnArmAndGunToDefault(mgr, false); - if (x834_28_ || (x2ec_lastFireButtonStates & 0x1) != 0) + if (x834_28_requestImmediateRecharge || (x2ec_lastFireButtonStates & 0x1) != 0) { if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - x32c_ = 1; - x834_28_ = false; + x32c_chargePhase = EChargePhase::ChargeRequested; + x834_28_requestImmediateRecharge = false; } - x832_30_ = false; - x338_ = 6; + x832_30_requestReturnToDefault = false; + x338_nextState = ENextState::SetupBeam; break; default: break; @@ -1060,12 +1163,12 @@ void CPlayerGun::StartPhazonBeamTransition(bool active, CStateManager& mgr, CPla x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); x72c_currentBeam->EnableFx(true); x72c_currentBeam->SetLeavingBeam(false); - PlayAnim(NWeaponTypes::EGunAnimType::Ten, false); - if (x833_31_) + PlayAnim(NWeaponTypes::EGunAnimType::ToBeam, false); + if (x833_31_inFreeLook) EnterFreeLook(mgr); - else if (x832_30_) + else if (x832_30_requestReturnToDefault) ReturnArmAndGunToDefault(mgr, false); - x832_30_ = false; + x832_30_requestReturnToDefault = false; } void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) @@ -1089,9 +1192,9 @@ void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) } } - switch (x33c_gunOverrideMode) + switch (x33c_phazonBeamState) { - case EGunOverrideMode::One: + case EPhazonBeamState::Entering: if (x75c_phazonBeam) { x75c_phazonBeam->Update(dt, mgr); @@ -1099,12 +1202,12 @@ void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) { StartPhazonBeamTransition(true, mgr, *mgr.GetPlayerState()); SetPhazonBeamMorph(false); - x33c_gunOverrideMode = EGunOverrideMode::Three; - x338_ = 6; + x33c_phazonBeamState = EPhazonBeamState::Active; + x338_nextState = ENextState::SetupBeam; } } break; - case EGunOverrideMode::Two: + case EPhazonBeamState::Exiting: if (x738_nextBeam) { x738_nextBeam->Update(dt, mgr); @@ -1113,8 +1216,8 @@ void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) x835_25_inPhazonBeam = false; StartPhazonBeamTransition(false, mgr, *mgr.GetPlayerState()); SetPhazonBeamMorph(false); - x33c_gunOverrideMode = EGunOverrideMode::Normal; - x338_ = 6; + x33c_phazonBeamState = EPhazonBeamState::Inactive; + x338_nextState = ENextState::SetupBeam; } } break; @@ -1123,59 +1226,385 @@ void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) } } +void CPlayerGun::EnableChargeFx(EChargeState state, CStateManager& mgr) +{ + x72c_currentBeam->ActivateCharge(true, false); + SetGunLightActive(true, mgr); + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::One); + StopContinuousBeam(mgr, false); + + switch (x310_currentBeam) + { + case CPlayerState::EBeamId::Plasma: + case CPlayerState::EBeamId::Power: + x832_25_chargeEffectVisible = true; + default: + break; + } + + x2f8_stateFlags |= 0x7; + x318_comboAmmoIdx = 1; + x338_nextState = ENextState::StatusQuo; + x833_30_canShowAuxMuzzleEffect = true; + + x800_auxMuzzleGenerators[int(x320_currentAuxBeam)] = + std::make_unique(x7c0_auxMuzzleEffects[int(x320_currentAuxBeam)], + CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + + x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]->SetParticleEmission(true); +} + +static constexpr float kChargeSpeed = 1.f / CPlayerState::GetMissileComboChargeFactor(); +static constexpr float kChargeFxStart = 1.f / CPlayerState::GetMissileComboChargeFactor(); +static constexpr float kChargeAnimStart = 0.25f / CPlayerState::GetMissileComboChargeFactor(); +static constexpr float kChargeStart = 0.025f / CPlayerState::GetMissileComboChargeFactor(); + +static const u16 skBeamChargeUpSound[] = { 1766, 1759, 1844, 1839 }; + void CPlayerGun::UpdateChargeState(float dt, CStateManager& mgr) { + switch (x32c_chargePhase) + { + case EChargePhase::ChargeRequested: + x340_chargeBeamFactor = 0.f; + x330_chargeState = EChargeState::Normal; + x832_27_chargeAnimStarted = false; + x834_24_charging = true; + x32c_chargePhase = EChargePhase::AnimAndSfx; + break; + case EChargePhase::AnimAndSfx: + if (!x832_27_chargeAnimStarted) + { + if (x340_chargeBeamFactor > kChargeStart && x832_25_chargeEffectVisible) + x832_25_chargeEffectVisible = false; + if (x340_chargeBeamFactor > kChargeAnimStart) + { + PlayAnim(NWeaponTypes::EGunAnimType::ChargeUp, false); + if (!x2e0_chargeSfx) + x2e0_chargeSfx = PlaySfx(skBeamChargeUpSound[int(x310_currentBeam)], + x834_27_underwater, true, 0.165f); + if (x830_chargeRumbleHandle == -1) + x830_chargeRumbleHandle = mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::Twelve, 1.f, + ERumblePriority::Three); + x832_27_chargeAnimStarted = true; + } + } + else + { + if (x340_chargeBeamFactor >= kChargeFxStart && (x2f8_stateFlags & 0x8) != 0x8) + { + x832_25_chargeEffectVisible = true; + x832_27_chargeAnimStarted = false; + x32c_chargePhase = EChargePhase::FxGrowing; + x330_chargeState = EChargeState::Charged; + EnableChargeFx(EChargeState::Charged, mgr); + PlayAnim(NWeaponTypes::EGunAnimType::ChargeLoop, true); + } + } + break; + case EChargePhase::FxGrowing: + if (x340_chargeBeamFactor >= 1.f) + x32c_chargePhase = EChargePhase::FxGrown; + break; + case EChargePhase::ComboXfer: + if (x344_comboXferTimer >= 1.f) + { + x32c_chargePhase = EChargePhase::ComboXferDone; + x832_25_chargeEffectVisible = false; + } + break; + case EChargePhase::ComboXferDone: + x32c_chargePhase = EChargePhase::ComboFire; + x348_chargeCancelTimer = 0.f; + break; + case EChargePhase::ComboFire: + x740_grappleArm->EnterComboFire(s32(x310_currentBeam), mgr); + x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::ComboFire, mgr, 0.f, false); + x72c_currentBeam->PlayPasAnim(SamusGun::EAnimationState::ComboFire, mgr, 0.f); + x833_31_inFreeLook = false; + x32c_chargePhase = EChargePhase::ComboFireDone; + break; + case EChargePhase::ChargeCancelled: + if ((x2f8_stateFlags & 0x10) != 0x10) + { + x348_chargeCancelTimer += dt; + if (x348_chargeCancelTimer >= 0.3f && x72c_currentBeam->IsChargeAnimOver()) + x32c_chargePhase = EChargePhase::ChargeDone; + } + else + { + x832_24_cancellingCharge = false; + } + break; + case EChargePhase::ChargeDone: + ResetCharge(mgr, false); + Reset(mgr, false); + break; + default: + break; + } + if (x2e0_chargeSfx) + CSfxManager::PitchBend(x2e0_chargeSfx, x834_27_underwater ? -1.f : 0.f); + if (x32c_chargePhase > EChargePhase::NotCharging && x32c_chargePhase < EChargePhase::FxGrown) + { + x340_chargeBeamFactor += kChargeSpeed * dt; + if (x340_chargeBeamFactor > 1.f) + x340_chargeBeamFactor = 1.f; + } } void CPlayerGun::UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr) { + zeus::CVector3f firePoint = + x4a8_gunWorldXf * x418_beamLocalXf.origin + mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); + bool done = x744_auxWeapon->UpdateComboFx(dt, sGunScale, firePoint, targetXf, mgr); + if ((x2f8_stateFlags & 0x10) == 0x10) + { + if (x310_currentBeam == CPlayerState::EBeamId::Wave && x744_auxWeapon->HasTarget(mgr) == kInvalidUniqueId) + { + TUniqueId targetId = GetTargetId(mgr); + if (targetId == kInvalidUniqueId) + targetId = mgr.GetPlayer().GetAimTarget(); + x744_auxWeapon->SetNewTarget(targetId, mgr); + } + if (done) + return; + done = x310_currentBeam == CPlayerState::EBeamId::Wave || x310_currentBeam == CPlayerState::EBeamId::Plasma; + if (!done) + if (x72c_currentBeam->ComboFireOver()) + done = true; + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Three); + if (done) + { + x32c_chargePhase = EChargePhase::ChargeDone; + ReturnArmAndGunToDefault(mgr, false); + if ((x2f8_stateFlags & 0x8) != 0x8) + { + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; + } + x318_comboAmmoIdx = 0; + x31c_missileMode = EMissleMode::Inactive; + } + } + else if (x833_28_phazonBeamActive) + { + static_cast(x72c_currentBeam)->UpdateBeam(dt, targetXf, x418_beamLocalXf.origin, mgr); + } + else if (x310_currentBeam == CPlayerState::EBeamId::Plasma) + { + static_cast(x72c_currentBeam)->UpdateBeam(dt, targetXf, x418_beamLocalXf.origin, mgr); + } +} +void CPlayerGun::DoUserAnimEvent(float dt, CStateManager& mgr, const CInt32POINode& node, EUserEventType type) +{ + switch (type) + { + case EUserEventType::Projectile: + if (x32c_chargePhase != EChargePhase::ComboFireDone) + return; + bool doFireSecondary; + if (x310_currentBeam != CPlayerState::EBeamId::Wave && x310_currentBeam != CPlayerState::EBeamId::Plasma) + doFireSecondary = true; + else + doFireSecondary = (x2ec_lastFireButtonStates & 0x1) != 0; + if (doFireSecondary) + FireSecondary(dt, mgr); + if ((x2f8_stateFlags & 0x10) != 0x10) + x2f8_stateFlags |= 0x10; + CancelCharge(mgr, true); + if (doFireSecondary) + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Two); + break; + default: + break; + } } void CPlayerGun::DoUserAnimEvents(float dt, CStateManager& mgr) { - + zeus::CVector3f posToCam = + mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x3e8_xf.origin; + const CAnimData& animData = *x72c_currentBeam->GetSolidModelData().GetAnimationData(); + for (int i=0 ; i act = mgr.GetObjectById(ret)) + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Target)) + ret = kInvalidUniqueId; + return ret; } void CPlayerGun::CancelLockOn() { - + if (x832_29_lockedOn) + { + x832_29_lockedOn = false; + x6a0_motionState.SetState(CMotionState::EMotionState::CancelLockOn); + if (x32c_chargePhase == EChargePhase::NotCharging && x318_comboAmmoIdx != 1) + PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); + } } +static const CPlayerState::EItemType skItemArr[] = +{ + CPlayerState::EItemType::Invalid, + CPlayerState::EItemType::Missiles +}; + +static const u16 skItemEmptySound[] = { 0, 1763 }; + void CPlayerGun::FireSecondary(float dt, CStateManager& mgr) { + if (mgr.GetCameraManager()->IsInCinematicCamera()) + return; + if (x835_25_inPhazonBeam || x318_comboAmmoIdx == 0 || + !mgr.GetPlayerState()->HasPowerUp(skItemArr[x318_comboAmmoIdx]) || (x2f8_stateFlags & 0x4) != 0x4) + { + PlaySfx(1781, x834_27_underwater, false, 0.165f); + return; + } + + bool comboFired = false; + if (x318_comboAmmoIdx == 1) + { + x300_remainingMissiles = mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles); + if (mgr.GetWeaponIdCount(x538_playerId, EWeaponType::Missile) < 3 && x300_remainingMissiles != 0) + { + mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::Missiles, + x832_26_comboFiring ? + mgr.GetPlayerState()->GetMissileCostForAltAttack() : 1); + comboFired = true; + } + if (x300_remainingMissiles > 5) + x300_remainingMissiles = 5; + else + x300_remainingMissiles -= 1; + } + + if (comboFired) + { + TUniqueId targetId = GetTargetId(mgr); + if (x832_26_comboFiring && targetId == kInvalidUniqueId && x310_currentBeam == CPlayerState::EBeamId::Wave) + targetId = mgr.GetPlayer().GetAimTarget(); + zeus::CTransform fireXf = x833_29_pointBlankWorldSurface ? + x448_elbowWorldXf : x4a8_gunWorldXf * x418_beamLocalXf; + if (!x833_29_pointBlankWorldSurface && x364_gunStrikeCoolTimer <= 0.f) + { + zeus::CVector3f backupOrigin = fireXf.origin; + fireXf = x478_assistAimXf; + fireXf.origin = backupOrigin; + } + fireXf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); + x744_auxWeapon->Fire(x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf, + mgr, x72c_currentBeam->GetWeaponType(), targetId); + mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::Zero); + x3a0_missileExitTimer = 7.f; + if (!x832_26_comboFiring) + { + PlayAnim(NWeaponTypes::EGunAnimType::MissileShoot, false); + x338_nextState = x300_remainingMissiles > 0 ? ENextState::MissileReload : ENextState::MissileShotDone; + x2f8_stateFlags &= ~0x4; + } + } + else + { + PlaySfx(skItemEmptySound[x318_comboAmmoIdx], x834_27_underwater, false, 0.165f); + } } void CPlayerGun::ResetCharged(float dt, CStateManager& mgr) { - if (x832_26_) + if (x832_26_comboFiring) return; - if (x32c_ >= 3) + if (x32c_chargePhase >= EChargePhase::FxGrowing) { - x833_30_ = false; + x833_30_canShowAuxMuzzleEffect = false; UpdateNormalShotCycle(dt, mgr); - x832_24_ = true; + x832_24_cancellingCharge = true; CancelCharge(mgr, true); } - else if (x32c_ != 0) + else if (x32c_chargePhase != EChargePhase::NotCharging) { x320_currentAuxBeam = x310_currentBeam; - x833_30_ = true; - x32c_ = 10; + x833_30_canShowAuxMuzzleEffect = true; + x32c_chargePhase = EChargePhase::ChargeDone; } StopChargeSound(mgr); } void CPlayerGun::ActivateCombo(CStateManager& mgr) { + if (x832_26_comboFiring) + return; + if (mgr.GetPlayerState()->GetItemAmount(skItemArr[x318_comboAmmoIdx]) >= + mgr.GetPlayerState()->GetMissileCostForAltAttack()) + { + bool canFire = true; + if (x310_currentBeam == CPlayerState::EBeamId::Plasma) + canFire = !x834_27_underwater; + if (canFire) + { + x832_26_comboFiring = true; + const auto& xferEffect = x72c_currentBeam->GetComboXferDescr(); + if (xferEffect.IsLoaded()) + { + x77c_comboXferGen = + std::make_unique(xferEffect, CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + x77c_comboXferGen->SetGlobalScale(sGunScale); + } + x72c_currentBeam->EnableCharge(true); + StopChargeSound(mgr); + PlaySfx(1762, x834_27_underwater, false, 0.165f); + x32c_chargePhase = EChargePhase::ComboXfer; + } + } + else + { + PlaySfx(1781, x834_27_underwater, false, 0.165f); + } } void CPlayerGun::ProcessChargeState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt) @@ -1184,20 +1613,21 @@ void CPlayerGun::ProcessChargeState(u32 releasedStates, u32 pressedStates, CStat ResetCharged(dt, mgr); if ((pressedStates & 0x1) != 0) { - if (x32c_ == 0 && (pressedStates & 0x1) != 0 && x348_ == 0.f && x832_28_) + if (x32c_chargePhase == EChargePhase::NotCharging && (pressedStates & 0x1) != 0 && + x348_chargeCancelTimer == 0.f && x832_28_readyForShot) { UpdateNormalShotCycle(dt, mgr); - x32c_ = 1; + x32c_chargePhase = EChargePhase::ChargeRequested; } } else if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::Missiles) && (pressedStates & 0x2) != 0) { - if (x32c_ >= 4) + if (x32c_chargePhase >= EChargePhase::FxGrown) { if (mgr.GetPlayerState()->HasPowerUp(skBeamComboArr[int(x310_currentBeam)])) ActivateCombo(mgr); } - else if (x32c_ == 0) + else if (x32c_chargePhase == EChargePhase::NotCharging) { FireSecondary(dt, mgr); } @@ -1207,7 +1637,7 @@ void CPlayerGun::ProcessChargeState(u32 releasedStates, u32 pressedStates, CStat void CPlayerGun::ResetNormal(CStateManager& mgr) { Reset(mgr, false); - x832_28_ = false; + x832_28_readyForShot = false; } void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr) @@ -1216,17 +1646,18 @@ void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr) return; if (mgr.GetCameraManager()->IsInCinematicCamera()) return; - x832_25_ = x833_28_phazonBeamActive || x310_currentBeam != CPlayerState::EBeamId::Plasma || x32c_ != 0; - x30c_ += 1; + x832_25_chargeEffectVisible = x833_28_phazonBeamActive || x310_currentBeam != CPlayerState::EBeamId::Plasma || + x32c_chargePhase != EChargePhase::NotCharging; + x30c_rapidFireShots += 1; zeus::CTransform xf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : x4a8_gunWorldXf * x418_beamLocalXf; - if (!x833_29_pointBlankWorldSurface && x364_ <= 0.f) + if (!x833_29_pointBlankWorldSurface && x364_gunStrikeCoolTimer <= 0.f) { zeus::CVector3f oldOrigin = xf.origin; xf = x478_assistAimXf; xf.origin = oldOrigin; } xf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); - x38c_ = 0.0625f; + x38c_muzzleEffectVisTimer = 0.0625f; TUniqueId homingTarget; if (x72c_currentBeam->GetVelocityInfo().GetTargetHoming(int(x330_chargeState))) homingTarget = GetTargetId(mgr); @@ -1240,7 +1671,7 @@ void CPlayerGun::ProcessNormalState(u32 releasedStates, u32 pressedStates, CStat { if ((releasedStates & 0x1) != 0) ResetNormal(mgr); - if ((pressedStates & 0x1) != 0 && x348_ == 0.f && x832_28_) + if ((pressedStates & 0x1) != 0 && x348_chargeCancelTimer == 0.f && x832_28_readyForShot) UpdateNormalShotCycle(dt, mgr); else if ((pressedStates & 0x2) != 0) FireSecondary(dt, mgr); @@ -1253,10 +1684,10 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt u32 pressedStates = x2f4_fireButtonStates & (oldFiring ^ x2f4_fireButtonStates); x2f0_pressedFireButtonStates = pressedStates; u32 releasedStates = oldFiring & (oldFiring ^ x2f4_fireButtonStates); - x832_28_ = false; + x832_28_readyForShot = false; CPlayer& player = mgr.GetPlayer(); - if (!x832_24_ && !x834_30_inBigStrike) + if (!x832_24_cancellingCharge && !x834_30_inBigStrike) { float coolDown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; if ((pressedStates & 0x1) == 0) @@ -1270,9 +1701,9 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt player.GetGrappleState() == CPlayer::EGrappleState::None && mgr.GetPlayerState()->GetTransitioningVisor() != CPlayerState::EPlayerVisor::Scan && mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan && - (x2ec_lastFireButtonStates & 0x1) != 0 && x32c_ == 0) + (x2ec_lastFireButtonStates & 0x1) != 0 && x32c_chargePhase == EChargePhase::NotCharging) { - x832_28_ = true; + x832_28_readyForShot = true; pressedStates |= 0x1; x390_cooldown = 0.f; } @@ -1280,14 +1711,14 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt } else if (x390_cooldown >= coolDown) { - x832_28_ = true; + x832_28_readyForShot = true; x390_cooldown = 0.f; } x390_cooldown += dt; } - if (x834_28_) - x834_28_ = (x2ec_lastFireButtonStates & 0x1) != 0; + if (x834_28_requestImmediateRecharge) + x834_28_requestImmediateRecharge = (x2ec_lastFireButtonStates & 0x1) != 0; if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { @@ -1305,7 +1736,7 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt else x53a_powerBomb = kInvalidUniqueId; } - if (((pressedStates & 0x1) != 0 || x32c_ != 0) && + if (((pressedStates & 0x1) != 0 || x32c_chargePhase != EChargePhase::NotCharging) && mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::MorphBallBombs)) { if (x835_28_bombReady) @@ -1321,24 +1752,25 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt } } } - else if ((x2f8_ & 0x8) != 0x8 && + else if ((x2f8_stateFlags & 0x8) != 0x8 && player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) { - if ((pressedStates & 0x2) != 0 && !x318_ && (x2f8_ & 0x2) != 0x2 && !x32c_) + if ((pressedStates & 0x2) != 0 && x318_comboAmmoIdx == 0 && + (x2f8_stateFlags & 0x2) != 0x2 && x32c_chargePhase == EChargePhase::NotCharging) { u32 missileCount = mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles); - if (x338_ != 1 && x338_ != 2) + if (x338_nextState != ENextState::EnterMissile && x338_nextState != ENextState::ExitMissile) { if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::Missiles) && missileCount > 0) { - x300_ = missileCount; - if (x300_ > 5) - x300_ = 5; + x300_remainingMissiles = missileCount; + if (x300_remainingMissiles > 5) + x300_remainingMissiles = 5; if (!x835_25_inPhazonBeam) { - x2f8_ &= ~0x1; - x2f8_ |= 0x6; - x318_ = 1; + x2f8_stateFlags &= ~0x1; + x2f8_stateFlags |= 0x6; + x318_comboAmmoIdx = 1; x31c_missileMode = EMissleMode::Active; } FireSecondary(dt, mgr); @@ -1356,18 +1788,18 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt { if (x3a4_fidget.GetState() == CFidget::EState::Zero) { - if ((x2f8_ & 0x10) == 0x10 && x744_auxWeapon->IsComboFxActive(mgr)) + if ((x2f8_stateFlags & 0x10) == 0x10 && x744_auxWeapon->IsComboFxActive(mgr)) { if (x2ec_lastFireButtonStates == 0 || (x310_currentBeam == CPlayerState::EBeamId::Wave && x833_29_pointBlankWorldSurface)) { - StopContinuousBeam(mgr, (x2f8_ & 0x8) == 0x8); + StopContinuousBeam(mgr, (x2f8_stateFlags & 0x8) == 0x8); } } else { if (mgr.GetPlayerState()->ItemEnabled(CPlayerState::EItemType::ChargeBeam) && - x33c_gunOverrideMode == EGunOverrideMode::Normal) + x33c_phazonBeamState == EPhazonBeamState::Inactive) ProcessChargeState(releasedStates, pressedStates, mgr, dt); else ProcessNormalState(releasedStates, pressedStates, mgr, dt); @@ -1379,7 +1811,7 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt void CPlayerGun::EnterFreeLook(CStateManager& mgr) { - if (!x832_30_) + if (!x832_30_requestReturnToDefault) x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::FreeLook, mgr, 0.f, false); x740_grappleArm->EnterFreeLook(x835_25_inPhazonBeam ? 1 : s32(x310_currentBeam), x73c_gunMotion->GetFreeLookSetId(), mgr); @@ -1424,7 +1856,7 @@ void CPlayerGun::AsyncLoadFidget(CStateManager& mgr) { x72c_currentBeam->AsyncLoadFidget(mgr, (x3a4_fidget.GetState() == CFidget::EState::Three ? SamusGun::EFidgetType::Zero : x3a4_fidget.GetType()), x3a4_fidget.GetParm2()); - x832_31_ = false; + x832_31_inRestPose = false; } if ((x2fc_fidgetAnimBits & 0x4) == 0x4) if (CGunController* gc = x740_grappleArm->GunController()) @@ -1452,11 +1884,11 @@ void CPlayerGun::EnterFidget(CStateManager& mgr) if ((x2fc_fidgetAnimBits & 0x1) == 0x1) { x73c_gunMotion->EnterFidget(mgr, x3a4_fidget.GetType(), x3a4_fidget.GetParm2()); - x834_25_ = true; + x834_25_gunMotionFidgeting = true; } else { - x834_25_ = false; + x834_25_gunMotionFidgeting = false; } if ((x2fc_fidgetAnimBits & 0x2) == 0x2) @@ -1471,51 +1903,52 @@ void CPlayerGun::EnterFidget(CStateManager& mgr) x3a4_fidget.DoneLoading(); } -void CPlayerGun::UpdateGunIdle(bool b1, float camBobT, float dt, CStateManager& mgr) +void CPlayerGun::UpdateGunIdle(bool inStrikeCooldown, float camBobT, float dt, CStateManager& mgr) { CPlayer& player = mgr.GetPlayer(); - if (player.IsInFreeLook() && !x832_29_ && !x740_grappleArm->IsGrappling() && + if (player.IsInFreeLook() && !x832_29_lockedOn && !x740_grappleArm->IsGrappling() && x3a4_fidget.GetState() != CFidget::EState::Three && player.GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn && !x834_30_inBigStrike) { - if ((x2f8_ & 0x8) != 0x8) + if ((x2f8_stateFlags & 0x8) != 0x8) { - if (!x833_31_ && !x834_26_) + if (!x833_31_inFreeLook && !x834_26_animPlaying) { - if (x388_ < 0.25f) - x388_ += dt; - if (x388_ >= 0.25f && !x740_grappleArm->IsSuitLoading()) + if (x388_enterFreeLookDelayTimer < 0.25f) + x388_enterFreeLookDelayTimer += dt; + if (x388_enterFreeLookDelayTimer >= 0.25f && !x740_grappleArm->IsSuitLoading()) { EnterFreeLook(mgr); - x833_31_ = true; + x833_31_inFreeLook = true; } } else { - x388_ = 0.f; - if (x834_26_) + x388_enterFreeLookDelayTimer = 0.f; + if (x834_26_animPlaying) ResetIdle(mgr); } } } else { - if (x833_31_) + if (x833_31_inFreeLook) { - if ((x2f8_ & 0x10) != 0x10) + if ((x2f8_stateFlags & 0x10) != 0x10) { x73c_gunMotion->ReturnToDefault(mgr, x834_30_inBigStrike); x740_grappleArm->ReturnToDefault(mgr, 0.f, false); } - x833_31_ = false; + x833_31_inFreeLook = false; } - x388_ = 0.f; + x388_enterFreeLookDelayTimer = 0.f; if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { x833_24_isFidgeting = (player.GetSurfaceRestraint() != CPlayer::ESurfaceRestraints::Water && mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan && - (x2f4_fireButtonStates & 0x3) == 0 && x32c_ == 0 && !x832_29_ && (x2f8_ & 0x8) != 0x8 && - x364_ <= 0.f && player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround && + (x2f4_fireButtonStates & 0x3) == 0 && x32c_chargePhase == EChargePhase::NotCharging && + !x832_29_lockedOn && (x2f8_stateFlags & 0x8) != 0x8 && x364_gunStrikeCoolTimer <= 0.f && + player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround && !player.IsInFreeLook() && !player.GetFreeLookStickState() && x304_ == 0 && std::fabs(player.GetAngularVelocityOR().angle()) <= 0.1f && camBobT <= 0.01f && !mgr.GetCameraManager()->IsInCinematicCamera() && @@ -1526,59 +1959,59 @@ void CPlayerGun::UpdateGunIdle(bool b1, float camBobT, float dt, CStateManager& { if (!x834_30_inBigStrike) { - bool r19 = camBobT > 0.01f && (x2f4_fireButtonStates & 0x3) == 0; - if (r19) + bool doWander = camBobT > 0.01f && (x2f4_fireButtonStates & 0x3) == 0; + if (doWander) { x370_gunMotionSpeedMult = 1.f; x374_ = 0.f; - if (x364_ <= 0.f && x368_ <= 0.f) + if (x364_gunStrikeCoolTimer <= 0.f && x368_idleWanderDelayTimer <= 0.f) { - x368_ = 8.f; + x368_idleWanderDelayTimer = 8.f; x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Wander, mgr, 0.f, false); - x324_ = 1; + x324_idleState = EIdleState::Wander; x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::Walk, mgr); } - x368_ -= dt; + x368_idleWanderDelayTimer -= dt; x360_ -= dt; } - if (!r19 || x834_26_) + if (!doWander || x834_26_animPlaying) ResetIdle(mgr); } if (x394_damageTimer > 0.f) { x394_damageTimer -= dt; } - else if (!x834_31_) + else if (!x834_31_gunMotionInFidgetBasePosition) { x394_damageTimer = 0.f; - x834_31_ = true; + x834_31_gunMotionInFidgetBasePosition = true; x73c_gunMotion->BasePosition(true); } else if (!x73c_gunMotion->GetModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body")) { x834_30_inBigStrike = false; - x834_31_ = false; + x834_31_gunMotionInFidgetBasePosition = false; } } else { - switch (x3a4_fidget.Update(x2ec_lastFireButtonStates, camBobT > 0.01f, b1, dt, mgr)) + switch (x3a4_fidget.Update(x2ec_lastFireButtonStates, camBobT > 0.01f, inStrikeCooldown, dt, mgr)) { case CFidget::EState::Zero: - if (x324_ != 2) + if (x324_idleState != EIdleState::Idle) { x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Idle, mgr, 0.f, false); - x324_ = 2; + x324_idleState = EIdleState::Idle; } x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::WalkNoBob, mgr); break; case CFidget::EState::One: case CFidget::EState::Two: case CFidget::EState::Three: - if (x324_ != 0) + if (x324_idleState != EIdleState::NotIdle) { x73c_gunMotion->BasePosition(false); - x324_ = 0; + x324_idleState = EIdleState::NotIdle; } AsyncLoadFidget(mgr); break; @@ -1590,9 +2023,9 @@ void CPlayerGun::UpdateGunIdle(bool b1, float camBobT, float dt, CStateManager& case CFidget::EState::Five: x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::Walk, mgr); x833_24_isFidgeting = false; - x834_26_ = x834_25_ ? x73c_gunMotion->IsAnimPlaying() : + x834_26_animPlaying = x834_25_gunMotionFidgeting ? x73c_gunMotion->IsAnimPlaying() : x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body"); - if (!x834_26_) + if (!x834_26_animPlaying) { x3a4_fidget.ResetMinor(); ReturnToRestPose(); @@ -1668,95 +2101,95 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM x73c_gunMotion->Update(advDt * x370_gunMotionSpeedMult, mgr); x740_grappleArm->Update(grappleSwingT, advDt, mgr); - if (x338_ != 0) + if (x338_nextState != ENextState::StatusQuo) { if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipeDone) { - if (x338_ == 5) + if (x338_nextState == ENextState::ChangeWeapon) { ChangeWeapon(playerState, mgr); - x338_ = 0; + x338_nextState = ENextState::StatusQuo; } } else if (!x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body") || - x832_30_) + x832_30_requestReturnToDefault) { - bool r24 = true; - switch (x338_) + bool statusQuo = true; + switch (x338_nextState) { - case 1: - x2f8_ &= 0x1; - x2f8_ |= 0x6; - x318_ = 1; + case ENextState::EnterMissile: + x2f8_stateFlags &= ~0x1; + x2f8_stateFlags |= 0x6; + x318_comboAmmoIdx = 1; x31c_missileMode = EMissleMode::Active; break; - case 2: - if ((x2f8_ & 0x8) != 0x8) + case ENextState::ExitMissile: + if ((x2f8_stateFlags & 0x8) != 0x8) { - x2f8_ |= 0x1; - x2f8_ &= 0xFFE9; + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; } - x318_ = 0; + x318_comboAmmoIdx = 0; x31c_missileMode = EMissleMode::Inactive; x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; break; - case 4: + case ENextState::MissileReload: PlayAnim(NWeaponTypes::EGunAnimType::MissileReload, false); - x338_ = 3; - r24 = false; + x338_nextState = ENextState::MissileShotDone; + statusQuo = false; break; - case 3: - x2f8_ |= 0x4; + case ENextState::MissileShotDone: + x2f8_stateFlags |= 0x4; break; - case 5: + case ENextState::ChangeWeapon: ChangeWeapon(playerState, mgr); break; - case 6: + case ENextState::SetupBeam: x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; - x2f8_ &= ~0x8; - if ((x2f8_ & 0x8) != 0x8) + x2f8_stateFlags &= ~0x8; + if ((x2f8_stateFlags & 0x8) != 0x8) { - x2f8_ |= 0x1; - x2f8_ &= 0xFFE9; + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; } - x318_ = 0; + x318_comboAmmoIdx = 0; x31c_missileMode = EMissleMode::Inactive; break; - case 8: + case ENextState::EnterPhazonBeam: if (x75c_phazonBeam->IsLoaded()) break; x72c_currentBeam->SetLeavingBeam(true); x75c_phazonBeam->Load(mgr, false); - x33c_gunOverrideMode = EGunOverrideMode::One; + x33c_phazonBeamState = EPhazonBeamState::Entering; break; - case 9: + case ENextState::ExitPhazonBeam: if (x738_nextBeam->IsLoaded()) break; x72c_currentBeam->SetLeavingBeam(true); x738_nextBeam->Load(mgr, false); - x33c_gunOverrideMode = EGunOverrideMode::Two; + x33c_phazonBeamState = EPhazonBeamState::Exiting; break; default: break; } - if (r24) - x338_ = 0; + if (statusQuo) + x338_nextState = ENextState::StatusQuo; } } - if (x37c_ < 0.2f) + if (x37c_rapidFireShotsDecayTimer < 0.2f) { - x37c_ += advDt; + x37c_rapidFireShotsDecayTimer += advDt; } else { - x37c_ = 0.f; - if (x30c_ > 0) - x30c_ -= 1; + x37c_rapidFireShotsDecayTimer = 0.f; + if (x30c_rapidFireShots > 0) + x30c_rapidFireShots -= 1; } - if (x32c_ != 0 && !player.GetFrozenState()) + if (x32c_chargePhase != EChargePhase::NotCharging && !player.GetFrozenState()) { x34c_shakeX = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor; x350_shakeZ = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor; @@ -1773,11 +2206,13 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM if (x740_grappleArm->GetActive() && !x740_grappleArm->IsGrappling()) UpdateLeftArmTransform(x72c_currentBeam->GetSolidModelData(), mgr); - x6a0_motionState.Update(x2f0_pressedFireButtonStates != 0 && x832_28_ && x32c_ < 2 && + x6a0_motionState.Update(x2f0_pressedFireButtonStates != 0 && x832_28_readyForShot && + x32c_chargePhase < EChargePhase::AnimAndSfx && !player.IsInFreeLook(), advDt, x4a8_gunWorldXf, mgr); x72c_currentBeam->GetSolidModelData().AdvanceParticles(x4a8_gunWorldXf, advDt, mgr); - x72c_currentBeam->UpdateGunFx(x380_ > 2.f && x378_ > 0.15f, dt, mgr, x508_elbowLocalXf); + x72c_currentBeam->UpdateGunFx(x380_shotSmokeTimer > 2.f && x378_shotSmokeStartTimer > 0.15f, + dt, mgr, x508_elbowLocalXf); zeus::CTransform beamWorldXf = x4a8_gunWorldXf * x418_beamLocalXf; @@ -1810,10 +2245,10 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM beamWorldXf.origin += camTrans; beamTargetXf.origin += camTrans; - if (x832_25_) + if (x832_25_chargeEffectVisible) { - bool emitting = x833_30_ ? x344_ < 1.f : false; - zeus::CVector3f scale((emitting && x832_26_) ? (1.f - x344_) * 2.f : 2.f); + bool emitting = x833_30_canShowAuxMuzzleEffect ? x344_comboXferTimer < 1.f : false; + zeus::CVector3f scale((emitting && x832_26_comboFiring) ? (1.f - x344_comboXferTimer) * 2.f : 2.f); x72c_currentBeam->UpdateMuzzleFx(advDt, scale, x418_beamLocalXf.origin, emitting); CElementGen& gen = *x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]; gen.SetGlobalOrientAndTrans(x418_beamLocalXf); @@ -1830,12 +2265,12 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM if (x835_26_phazonBeamMorphing) ProcessPhazonGunMorph(advDt, mgr); - if (x832_26_ && x77c_) + if (x832_26_comboFiring && x77c_comboXferGen) { - x77c_->SetGlobalTranslation(x418_beamLocalXf.origin); - x77c_->SetGlobalOrientation(x418_beamLocalXf.getRotation()); - x77c_->Update(advDt); - x344_ += advDt * 4.f; + x77c_comboXferGen->SetGlobalTranslation(x418_beamLocalXf.origin); + x77c_comboXferGen->SetGlobalOrientation(x418_beamLocalXf.getRotation()); + x77c_comboXferGen->Update(advDt); + x344_comboXferTimer += advDt * 4.f; } if (x35c_bombTime > 0.f) @@ -1845,7 +2280,7 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM x308_bombCount = 3; } - if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam) && x32c_ != 0) + if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam) && x32c_chargePhase != EChargePhase::NotCharging) { UpdateChargeState(advDt, mgr); } @@ -1861,10 +2296,10 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM if (x304_ == 1 && GetTargetId(mgr) != kInvalidUniqueId) { - if (!x832_29_ && !x832_26_ && (x2f8_ & 0x10) != 0x10) + if (!x832_29_lockedOn && !x832_26_comboFiring && (x2f8_stateFlags & 0x10) != 0x10) { - x832_29_ = true; - x6a0_motionState.SetState(CMotionState::EMotionState::Two); + x832_29_lockedOn = true; + x6a0_motionState.SetState(CMotionState::EMotionState::LockOn); ReturnArmAndGunToDefault(mgr, true); } } @@ -1874,43 +2309,43 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM } UpdateWeaponFire(advDt, playerState, mgr); - UpdateGunIdle(x364_ > 0.f, cameraBobT, advDt, mgr); + UpdateGunIdle(x364_gunStrikeCoolTimer > 0.f, cameraBobT, advDt, mgr); if ((x2ec_lastFireButtonStates & 0x1) == 0x1) { - x378_ = 0.f; + x378_shotSmokeStartTimer = 0.f; } - else if (x378_ < 2.f) + else if (x378_shotSmokeStartTimer < 2.f) { - x378_ += advDt; - if (x378_ > 1.f) + x378_shotSmokeStartTimer += advDt; + if (x378_shotSmokeStartTimer > 1.f) { - x30c_ = 0; - x380_ = 0.f; + x30c_rapidFireShots = 0; + x380_shotSmokeTimer = 0.f; } } - if (x38c_ > 0.f) - x38c_ -= advDt; + if (x38c_muzzleEffectVisTimer > 0.f) + x38c_muzzleEffectVisTimer -= advDt; - if (x30c_ > 5 && x380_ < 2.f) - x380_ += advDt; + if (x30c_rapidFireShots > 5 && x380_shotSmokeTimer < 2.f) + x380_shotSmokeTimer += advDt; - if (x384_ > 0.f) - x384_ -= advDt; + if (x384_gunStrikeDelayTimer > 0.f) + x384_gunStrikeDelayTimer -= advDt; - if (x364_ > 0.f) + if (x364_gunStrikeCoolTimer > 0.f) { x2f4_fireButtonStates = 0; - x364_ -= advDt; + x364_gunStrikeCoolTimer -= advDt; } - if (isUnmorphed && (x2f8_ & 0x4) == 0x4) + if (isUnmorphed && (x2f8_stateFlags & 0x4) == 0x4) { - x3a0_ -= advDt; - if (x3a0_ < 0.f) + x3a0_missileExitTimer -= advDt; + if (x3a0_missileExitTimer < 0.f) { - x3a0_ = 0.f; + x3a0_missileExitTimer = 0.f; ExitMissile(); } } @@ -1927,7 +2362,7 @@ void CPlayerGun::PreRender(const CStateManager& mgr, const zeus::CFrustum& frust { case CPlayerState::EPlayerVisor::Thermal: x0_lights.BuildConstantAmbientLighting( - zeus::CColor(zeus::clamp(0.6f, 0.5f * x380_ + 0.6f - x378_, 1.f), 1.f)); + zeus::CColor(zeus::clamp(0.6f, 0.5f * x380_shotSmokeTimer + 0.6f - x378_shotSmokeStartTimer, 1.f), 1.f)); break; case CPlayerState::EPlayerVisor::Combat: { @@ -2048,16 +2483,17 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co CGraphics::SetDepthRange(0.03125f, 0.125f); zeus::CTransform offsetWorldXf = zeus::CTransform::Translate(pos) * x4a8_gunWorldXf; zeus::CTransform elbowOffsetXf = offsetWorldXf * x508_elbowLocalXf; - if (x32c_ && (x2f8_ & 0x10) != 0x10) + if (x32c_chargePhase != EChargePhase::NotCharging && (x2f8_stateFlags & 0x10) != 0x10) offsetWorldXf.origin += zeus::CVector3f(x34c_shakeX, 0.f, x350_shakeZ); zeus::CTransform oldViewMtx = CGraphics::g_ViewMatrix; CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx); CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - if (x32c_ >= 4 && x32c_ < 5) + if (x32c_chargePhase >= EChargePhase::FxGrown && x32c_chargePhase < EChargePhase::ComboXfer) x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]->Render(); - if (x832_25_ && (x38c_ > 0.f || x32c_ > 2)) + if (x832_25_chargeEffectVisible && + (x38c_muzzleEffectVisTimer > 0.f || x32c_chargePhase > EChargePhase::AnimAndSfx)) x72c_currentBeam->DrawMuzzleFx(mgr); if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipe || @@ -2065,7 +2501,7 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co x774_holoTransitionGen->Render(); CGraphics::SetViewPointMatrix(oldViewMtx); - if ((x2f8_ & 0x10) == 0x10) + if ((x2f8_stateFlags & 0x10) == 0x10) x744_auxWeapon->RenderMuzzleFx(); x72c_currentBeam->PreRenderGunFx(mgr, offsetWorldXf); @@ -2125,8 +2561,8 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co CGraphics::SetModelMatrix(offsetWorldXf.inverse() * oldViewMtx); CGraphics::SetModelMatrix(zeus::CTransform::Identity()); x72c_currentBeam->PostRenderGunFx(mgr, offsetWorldXf); - if (x832_26_ && x77c_) - x77c_->Render(); + if (x832_26_comboFiring && x77c_comboXferGen) + x77c_comboXferGen->Render(); CGraphics::SetViewPointMatrix(oldViewMtx); RenderEnergyDrainEffects(mgr); @@ -2145,9 +2581,9 @@ void CPlayerGun::DropBomb(EBWeapon weapon, CStateManager& mgr) { if (weapon == EBWeapon::Bomb) { - if (x32c_ != 0) + if (x32c_chargePhase != EChargePhase::NotCharging) { - x32c_ = 0xA; + x32c_chargePhase = EChargePhase::ChargeDone; return; } diff --git a/Runtime/Weapon/CPlayerGun.hpp b/Runtime/Weapon/CPlayerGun.hpp index ca949a15e..409d0024c 100644 --- a/Runtime/Weapon/CPlayerGun.hpp +++ b/Runtime/Weapon/CPlayerGun.hpp @@ -38,12 +38,47 @@ public: Bomb, PowerBomb }; - enum class EGunOverrideMode + enum class EPhazonBeamState { - Normal, - One, - Two, - Three + Inactive, + Entering, + Exiting, + Active + }; + enum class EChargePhase + { + NotCharging, + ChargeRequested, + AnimAndSfx, + FxGrowing, + FxGrown, + ComboXfer, + ComboXferDone, + ComboFire, + ComboFireDone, + ChargeCancelled, + ChargeDone + }; + enum class ENextState + { + StatusQuo, + EnterMissile, + ExitMissile, + MissileShotDone, + MissileReload, + ChangeWeapon, + SetupBeam, + Seven, + EnterPhazonBeam, + ExitPhazonBeam + }; + enum class EIdleState + { + NotIdle, + Wander, + Idle, + Three, + Four }; private: class CGunMorph @@ -107,25 +142,31 @@ private: { Zero, One, - Two + LockOn, + CancelLockOn + }; + enum class EFireState + { + NotFiring, + StartFire, + Firing }; private: static float gGunExtendDistance; - bool x0_24_ = true; - float x4_ = 0.f; - float x8_ = 0.f; - float xc_ = 0.f; - float x10_ = 0.f; - float x14_ = 0.f; - float x18_ = 0.f; - float x1c_ = 0.f; + bool x0_24_extendParabola = true; + float x4_extendParabolaDelayTimer = 0.f; + float x8_fireTime = 0.f; + float xc_curExtendDist = 0.f; + float x10_curRotation = 0.f; + float x14_rotationT = 0.f; + float x18_startRotation = 0.f; + float x1c_endRotation = 0.f; EMotionState x20_state = EMotionState::Zero; - u32 x24_ = 0; + EFireState x24_fireState = EFireState::NotFiring; public: static void SetExtendDistance(float d) { gGunExtendDistance = d; } void SetState(EMotionState state) { x20_state = state; } - void Update(bool b1, float dt, zeus::CTransform& xf, CStateManager& mgr); - + void Update(bool firing, float dt, zeus::CTransform& xf, CStateManager& mgr); }; CActorLights x0_lights; @@ -136,49 +177,50 @@ private: u32 x2ec_lastFireButtonStates = 0; u32 x2f0_pressedFireButtonStates = 0; u32 x2f4_fireButtonStates = 0; - u32 x2f8_ = 1; + // 0x1: beam mode, 0x2: missile mode, 0x4: missile ready, 0x8: morphing, 0x10: combo fire + u32 x2f8_stateFlags = 0x1; u32 x2fc_fidgetAnimBits = 0; - u32 x300_ = 0; + u32 x300_remainingMissiles = 0; u32 x304_ = 0; u32 x308_bombCount = 3; - u32 x30c_ = 0; + u32 x30c_rapidFireShots = 0; CPlayerState::EBeamId x310_currentBeam = CPlayerState::EBeamId::Power; CPlayerState::EBeamId x314_nextBeam = CPlayerState::EBeamId::Power; - u32 x318_ = 0; + u32 x318_comboAmmoIdx = 0; EMissleMode x31c_missileMode = EMissleMode::Inactive; CPlayerState::EBeamId x320_currentAuxBeam = CPlayerState::EBeamId::Power; - u32 x324_ = 4; - u32 x328_ = 0x2000; - u32 x32c_ = 0; + EIdleState x324_idleState = EIdleState::Four; + float x328_animSfxPitch = 0.f; + EChargePhase x32c_chargePhase = EChargePhase::NotCharging; EChargeState x330_chargeState = EChargeState::Normal; u32 x334_ = 0; - u32 x338_ = 0; - EGunOverrideMode x33c_gunOverrideMode = EGunOverrideMode::Normal; + ENextState x338_nextState = ENextState::StatusQuo; + EPhazonBeamState x33c_phazonBeamState = EPhazonBeamState::Inactive; float x340_chargeBeamFactor = 0.f; - float x344_ = 0.f; - float x348_ = 0.f; + float x344_comboXferTimer = 0.f; + float x348_chargeCancelTimer = 0.f; float x34c_shakeX = 0.f; float x350_shakeZ = 0.f; float x354_bombFuseTime; float x358_bombDropDelayTime; float x35c_bombTime = 0.f; float x360_ = 0.f; - float x364_ = 0.f; - float x368_ = 0.f; + float x364_gunStrikeCoolTimer = 0.f; + float x368_idleWanderDelayTimer = 0.f; float x36c_ = 1.f; float x370_gunMotionSpeedMult = 1.f; float x374_ = 0.f; - float x378_ = 0.f; - float x37c_ = 0.f; - float x380_ = 0.f; - float x384_ = 0.f; - float x388_ = 0.f; - float x38c_ = 0.f; + float x378_shotSmokeStartTimer = 0.f; + float x37c_rapidFireShotsDecayTimer = 0.f; + float x380_shotSmokeTimer = 0.f; + float x384_gunStrikeDelayTimer = 0.f; + float x388_enterFreeLookDelayTimer = 0.f; + float x38c_muzzleEffectVisTimer = 0.f; float x390_cooldown = 0.f; float x394_damageTimer = 0.f; float x398_damageAmt = 0.f; float x39c_phazonMorphT = 0.f; - float x3a0_ = 0.f; + float x3a0_missileExitTimer = 0.f; CFidget x3a4_fidget; zeus::CVector3f x3dc_damageLocation; zeus::CTransform x3e8_xf; @@ -199,8 +241,7 @@ private: float x664_ = 0.f; float x668_aimVerticalSpeed; float x66c_aimHorizontalSpeed; - TUniqueId x670_ = kInvalidUniqueId; - u32 x674_ = 0; + std::pair x670_animSfx = {0xffff, {}}; CGunMorph x678_morph; CMotionState x6a0_motionState; zeus::CAABox x6c8_hologramClipCube; @@ -220,7 +261,7 @@ private: std::unique_ptr x75c_phazonBeam; CGunWeapon* x760_selectableBeams[4] = {}; // Used to be reserved_vector std::unique_ptr x774_holoTransitionGen; - std::unique_ptr x77c_; + std::unique_ptr x77c_comboXferGen; rstl::reserved_vector, 2>, 2> x784_bombEffects; rstl::reserved_vector, 5> x7c0_auxMuzzleEffects; rstl::reserved_vector, 5> x800_auxMuzzleGenerators; @@ -231,14 +272,14 @@ private: { struct { - bool x832_24_ : 1; - bool x832_25_ : 1; - bool x832_26_ : 1; - bool x832_27_ : 1; - bool x832_28_ : 1; - bool x832_29_ : 1; - bool x832_30_ : 1; - bool x832_31_ : 1; + bool x832_24_cancellingCharge : 1; + bool x832_25_chargeEffectVisible : 1; + bool x832_26_comboFiring : 1; + bool x832_27_chargeAnimStarted : 1; + bool x832_28_readyForShot : 1; + bool x832_29_lockedOn : 1; + bool x832_30_requestReturnToDefault : 1; + bool x832_31_inRestPose : 1; bool x833_24_isFidgeting : 1; bool x833_25_ : 1; @@ -246,17 +287,17 @@ private: bool x833_27_ : 1; bool x833_28_phazonBeamActive : 1; bool x833_29_pointBlankWorldSurface : 1; - bool x833_30_ : 1; - bool x833_31_ : 1; + bool x833_30_canShowAuxMuzzleEffect : 1; + bool x833_31_inFreeLook : 1; bool x834_24_charging : 1; - bool x834_25_ : 1; - bool x834_26_ : 1; + bool x834_25_gunMotionFidgeting : 1; + bool x834_26_animPlaying : 1; bool x834_27_underwater : 1; - bool x834_28_ : 1; + bool x834_28_requestImmediateRecharge : 1; bool x834_29_frozen : 1; bool x834_30_inBigStrike : 1; - bool x834_31_ : 1; + bool x834_31_gunMotionInFidgetBasePosition : 1; bool x835_24_canFirePhazon : 1; bool x835_25_inPhazonBeam : 1; @@ -277,7 +318,7 @@ private: void LoadHandAnimTokens(); void CreateGunLight(CStateManager& mgr); void DeleteGunLight(CStateManager& mgr); - void UpdateGunLight(const zeus::CTransform& pos, CStateManager& mgr); + void UpdateGunLight(const zeus::CTransform& xf, CStateManager& mgr); void SetGunLightActive(bool active, CStateManager& mgr); void SetPhazonBeamMorph(bool intoPhazonBeam); void Reset(CStateManager& mgr, bool b1); @@ -288,7 +329,7 @@ private: bool ExitMissile(); void StopChargeSound(CStateManager& mgr); void UnLoadFidget(); - void ReturnArmAndGunToDefault(CStateManager& mgr, bool b1); + void ReturnArmAndGunToDefault(CStateManager& mgr, bool returnToDefault); void ReturnToRestPose(); void ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr); void GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mData, const std::string& lctrName, @@ -298,8 +339,10 @@ private: void SetPhazonBeamFeedback(bool active); void StartPhazonBeamTransition(bool active, CStateManager& mgr, CPlayerState& playerState); void ProcessPhazonGunMorph(float dt, CStateManager& mgr); + void EnableChargeFx(EChargeState state, CStateManager& mgr); void UpdateChargeState(float dt, CStateManager& mgr); void UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr); + void DoUserAnimEvent(float dt, CStateManager& mgr, const CInt32POINode& node, EUserEventType type); void DoUserAnimEvents(float dt, CStateManager& mgr); TUniqueId GetTargetId(CStateManager& mgr) const; void CancelLockOn(); @@ -316,7 +359,7 @@ private: void AsyncLoadFidget(CStateManager& mgr); bool IsFidgetLoaded() const; void EnterFidget(CStateManager& mgr); - void UpdateGunIdle(bool b1, float camBobT, float dt, CStateManager& mgr); + void UpdateGunIdle(bool inStrikeCooldown, float camBobT, float dt, CStateManager& mgr); void RenderEnergyDrainEffects(const CStateManager& mgr) const; void DrawArm(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const; zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f& pos, const CGameCamera& cam) const; diff --git a/Runtime/Weapon/CPowerBeam.hpp b/Runtime/Weapon/CPowerBeam.hpp index 35dc68cf8..648aa31bd 100644 --- a/Runtime/Weapon/CPowerBeam.hpp +++ b/Runtime/Weapon/CPowerBeam.hpp @@ -10,7 +10,7 @@ class CPowerBeam : public CGunWeapon { TCachedToken x21c_shotSmoke; TCachedToken x228_power2nd1; - u32 x234_ = 0; + std::unique_ptr x234_shotSmokeGen; float x23c_ = 0.f; u32 x240_ = 0; bool x244_24 : 1; diff --git a/Runtime/Weapon/WeaponCommon.cpp b/Runtime/Weapon/WeaponCommon.cpp index f99ec1d16..c7cf3e15e 100644 --- a/Runtime/Weapon/WeaponCommon.cpp +++ b/Runtime/Weapon/WeaponCommon.cpp @@ -3,6 +3,8 @@ #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" #include "Character/CPrimitive.hpp" +#include "Audio/CSfxManager.hpp" +#include "CStateManager.hpp" namespace urde { @@ -78,5 +80,83 @@ void get_token_vector(CAnimData& animData, int animIdx, std::vector& tok primitive_set_to_token_vector(animData, prims, tokensOut, preLock); } +void do_sound_event(std::pair& sfxHandle, float& pitch, bool doPitchBend, u32 soundId, + float weight, u32 flags, float falloff, float maxDist, float minVol, float maxVol, + const zeus::CVector3f& posToCam, const zeus::CVector3f& pos, TAreaId aid, + CStateManager& mgr) +{ + if (posToCam.magSquared() >= maxDist * maxDist) + return; + + u16 useSfxId = CSfxManager::TranslateSFXID(u16(soundId)); + u32 useFlags = 0x1; // Continuous parameter update + if ((flags & 0x8) != 0) + useFlags |= 0x8; // Doppler effect + bool useAcoustics = (flags & 0x80) == 0; + + CAudioSys::C3DEmitterParmData parms; + parms.x0_pos = pos; + parms.xc_dir = zeus::CVector3f::skUp; + parms.x18_maxDist = maxDist; + parms.x1c_distComp = falloff; + parms.x20_flags = useFlags; + parms.x24_sfxId = useSfxId; + parms.x26_maxVol = maxVol; + parms.x27_minVol = minVol; + parms.x28_important = false; + parms.x29_prio = 0x7f; + + if (mgr.GetActiveRandom()->Float() <= weight) + { + if ((soundId & 0x80000000) != 0) + { + if (!sfxHandle.second) + { + CSfxHandle hnd; + if ((soundId & 0x40000000) != 0) + hnd = CSfxManager::SfxStart(useSfxId, 1.f, 0.f, true, 0x7f, true, aid); + else + hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); + if (hnd) + { + sfxHandle.first = useSfxId; + sfxHandle.second = hnd; + if (doPitchBend) + CSfxManager::PitchBend(hnd, pitch); + } + } + else + { + if (sfxHandle.first == useSfxId) + { + CSfxManager::UpdateEmitter(sfxHandle.second, parms.x0_pos, parms.xc_dir, parms.x26_maxVol); + } + else if ((flags & 0x4) != 0) // Pausable + { + CSfxManager::RemoveEmitter(sfxHandle.second); + CSfxHandle hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); + if (hnd) + { + sfxHandle.first = useSfxId; + sfxHandle.second = hnd; + if (doPitchBend) + CSfxManager::PitchBend(hnd, pitch); + } + } + } + } + else + { + CSfxHandle hnd; + if ((soundId & 0x40000000) != 0) + hnd = CSfxManager::SfxStart(useSfxId, 1.f, 0.f, true, 0x7f, false, aid); + else + hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, false, aid); + if (doPitchBend) + CSfxManager::PitchBend(hnd, pitch); + } + } +} + } } diff --git a/Runtime/Weapon/WeaponCommon.hpp b/Runtime/Weapon/WeaponCommon.hpp index 7bd88b667..7ab9dfdb3 100644 --- a/Runtime/Weapon/WeaponCommon.hpp +++ b/Runtime/Weapon/WeaponCommon.hpp @@ -3,6 +3,7 @@ #include "RetroTypes.hpp" #include "DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp" +#include "Audio/CSfxManager.hpp" #include namespace urde @@ -10,6 +11,8 @@ namespace urde class CAnimData; class CToken; class CPrimitive; +class CStateManager; + enum class EWeaponType { None = -1, @@ -35,17 +38,17 @@ namespace NWeaponTypes enum class EGunAnimType { - Zero, - One, - Two, - Three, - Four, + BasePosition, + Shoot, + ChargeUp, + ChargeLoop, + ChargeShoot, FromMissile, ToMissile, - Seven, + MissileShoot, MissileReload, FromBeam, - Ten + ToBeam }; void primitive_set_to_token_vector(const CAnimData& animData, const std::set& primSet, @@ -55,6 +58,10 @@ void lock_tokens(std::vector& anims); bool are_tokens_ready(const std::vector& anims); void get_token_vector(CAnimData& animData, int begin, int end, std::vector& tokensOut, bool preLock); void get_token_vector(CAnimData& animData, int animIdx, std::vector& tokensOut, bool preLock); +void do_sound_event(std::pair& sfxHandle, float& pitch, bool doPitchBend, u32 soundId, + float weight, u32 flags, float falloff, float maxDist, float minVol, float maxVol, + const zeus::CVector3f& posToCam, const zeus::CVector3f& pos, TAreaId aid, + CStateManager& mgr); } diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index 8e083690b..28e8adb1a 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -561,6 +561,7 @@ public: bool ValidateAimTargetId(TUniqueId, CStateManager& mgr); bool ValidateObjectForMode(TUniqueId, CStateManager& mgr) const; TUniqueId FindAimTargetId(CStateManager& mgr); + TUniqueId GetAimTarget() const { return x3f4_aimTarget; } TUniqueId CheckEnemiesAgainstOrbitZone(const std::vector&, EPlayerZoneInfo, EPlayerZoneType, CStateManager& mgr) const; TUniqueId FindOrbitTargetId(CStateManager& mgr); @@ -634,6 +635,7 @@ public: EPlayerScanState GetScanningState() const { return x3a8_scanState; } float GetScanningTime() const { return x3ac_scanningTime; } 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 IsNewScanScanning() const { return x9c6_30_newScanScanning; }