#include "MetroidPrime/Player/CPlayerGun.hpp"

#include "MetroidPrime/CAnimData.hpp"
#include "MetroidPrime/CAnimRes.hpp"
#include "MetroidPrime/CRainSplashGenerator.hpp"
#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/SFX/Weapons.h"
#include "MetroidPrime/Tweaks/CTweakGunRes.hpp"
#include "MetroidPrime/Tweaks/CTweakPlayerGun.hpp"
#include "MetroidPrime/Weapons/CAuxWeapon.hpp"
#include "MetroidPrime/Weapons/CIceBeam.hpp"
#include "MetroidPrime/Weapons/CPhazonBeam.hpp"
#include "MetroidPrime/Weapons/CPlasmaBeam.hpp"
#include "MetroidPrime/Weapons/CPowerBeam.hpp"
#include "MetroidPrime/Weapons/CPowerBomb.hpp"
#include "MetroidPrime/Weapons/CWaveBeam.hpp"
#include "MetroidPrime/Weapons/GunController/CGunMotion.hpp"
#include "MetroidPrime/Weapons/WeaponTypes.hpp"

#include "Kyoto/Audio/CSfxManager.hpp"
#include "Kyoto/Graphics/CModelFlags.hpp"
#include "Kyoto/Math/CAbsAngle.hpp"
#include "Kyoto/Math/CMath.hpp"
#include "Kyoto/Math/CRelAngle.hpp"
#include "Kyoto/Particles/CElementGen.hpp"
#include "Kyoto/Particles/CGenDescription.hpp"
#include "Kyoto/SObjectTag.hpp"

#include "Collision/CMaterialFilter.hpp"
#include "Collision/CMaterialList.hpp"

#include "MetaRender/CCubeRenderer.hpp"

#include "Weapons/IWeaponRenderer.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};

static const float chargeShakeTbl[3] = {
    -0.001f,
    0.f,
    0.001f,
};

const uint CPlayerGun::mHandAnimId[4] = {
    0,
    1,
    2,
    1,
};

static const CPlayerState::EItemType mBeamArr[4] = {
    CPlayerState::kIT_PowerBeam,
    CPlayerState::kIT_IceBeam,
    CPlayerState::kIT_WaveBeam,
    CPlayerState::kIT_PlasmaBeam,
};

static const CPlayerState::EItemType mBeamComboArr[4] = {
    CPlayerState::kIT_SuperMissile,
    CPlayerState::kIT_IceSpreader,
    CPlayerState::kIT_Wavebuster,
    CPlayerState::kIT_Flamethrower,
};

// static ControlMapper::ECommands mBeamCtrlCmd[4] = {
//     ControlMapper::kC_PowerBeam,
//     ControlMapper::kC_IceBeam,
//     ControlMapper::kC_WaveBeam,
//     ControlMapper::kC_PlasmaBeam,
// };

// constexpr std::array<ushort, 4> skFromMissileSound{
//     SFXwpn_from_missile_power,
//     SFXwpn_from_missile_ice,
//     SFXwpn_from_missile_wave,
//     SFXwpn_from_missile_plasma,
// };

// constexpr std::array<ushort, 4> mFromBeamSound{
//     SFXsfx0000,
//     SFXwpn_from_beam_ice,
//     SFXwpn_from_beam_wave,
//     SFXwpn_from_beam_plasma,
// };

// constexpr std::array<ushort, 4> skToMissileSound{
//     SFXwpn_to_missile_power,
//     SFXwpn_to_missile_ice,
//     SFXwpn_to_missile_wave,
//     SFXwpn_to_missile_plasma,
// };

// constexpr std::array<ushort, 4> mIntoBeamSound{
//     SFXsfx0000,
//     SFXwpn_into_beam_ice,
//     SFXwpn_into_beam_wave,
//     SFXwpn_into_beam_plasma,
// };

float CPlayerGun::kTractorBeamFactor = 0.25f / CPlayerState::GetMissileComboChargeFactor();
CVector3f CPlayerGun::kScaleVector(2.f, 2.f, 2.f);
float CPlayerGun::CMotionState::gGunExtendDistance = 0.125f;

static CColor kArmColor = CColor(0.75f, 0.5f, 0.f, 1.f);
static CMaterialFilter sAimFilter = CMaterialFilter::MakeIncludeExclude(
    CMaterialList(kMT_Solid), CMaterialList(kMT_ProjectilePassthrough));
static const float kChargeSpeed = 1.f / CPlayerState::GetMissileComboChargeFactor();
static const float kChargeStart = 0.025f / CPlayerState::GetMissileComboChargeFactor();
static const float kChargeFxStart = 1.f / CPlayerState::GetMissileComboChargeFactor();

// constexpr std::array<ushort, 4> skBeamChargeUpSound{
//     SFXwpn_chargeup_power,
//     SFXwpn_chargeup_ice,
//     SFXwpn_chargeup_wave,
//     SFXwpn_chargeup_plasma,
// };

static const CPlayerState::EItemType skItemArr[2] = {
    CPlayerState::kIT_Invalid,
    CPlayerState::kIT_Missiles,
};

static const CModelFlags kThermalFlags[4] = {
    CModelFlags::Normal(),
    CModelFlags::AlphaBlended(CColor(u8(255), u8(255), u8(255), u8(128))),
    CModelFlags::Normal(),
    CModelFlags::Normal(),
};

static const CModelFlags kHandThermalFlag(CModelFlags::kT_Additive, CColor::White());
static const CModelFlags kHandHoloFlag(CModelFlags::kT_One, kArmColor);

static ushort mItemEmptySound[2] = {
    CSfxManager::kInternalInvalidSfxId,
    SFXwpn_empty_action,
};

static ushort mIntoBeamSound[4] = {
    CSfxManager::kInternalInvalidSfxId,
    SFXwpn_into_beam_ice,
    SFXwpn_into_beam_wave,
    SFXwpn_into_beam_plasma,
};

static ushort mFromBeamSound[4] = {
    CSfxManager::kInternalInvalidSfxId,
    SFXwpn_from_beam_ice,
    SFXwpn_from_beam_wave,
    SFXwpn_from_beam_plasma,
};

CPlayerGun::CPlayerGun(TUniqueId playerId)
: x0_lights(8, CVector3f::Zero(), 4, 4, false, false, false, 0.1)
, x2ec_lastFireButtonStates(0)
, x2f0_pressedFireButtonStates(0)
, x2f4_fireButtonStates(0)
, x2f8_stateFlags(0x1)
, x2fc_fidgetAnimBits(0)
, x300_remainingMissiles(0)
, x304_(0)
, x308_bombCount(3)
, x30c_rapidFireShots(0)
, x310_currentBeam(CPlayerState::kBI_Power)
, x314_nextBeam(CPlayerState::kBI_Power)
, x318_comboAmmoIdx(0)
, x31c_missileMode(kMM_Inactive)
, x320_currentAuxBeam(CPlayerState::kBI_Power)
, x324_idleState(kIS_Four)
, x328_animSfxPitch(0.f)
, x32c_chargePhase(kCP_NotCharging)
, x330_chargeState(kCS_Normal)
, x334_(0)
, x338_nextState(kNS_StatusQuo)
, x33c_phazonBeamState(kPBS_Inactive)
, x340_chargeBeamFactor(0.f)
, x344_comboXferTimer(0.f)
, x348_chargeCooldownTimer(0.f)
, x34c_shakeX(0.f)
, x350_shakeZ(0.f)
, x354_bombFuseTime(gpTweakPlayerGun->GetBombFuseTime())
, x358_bombDropDelayTime(gpTweakPlayerGun->GetBombDropDelayTime())
, x35c_bombTime(0.f)
, x360_(0.f)
, x364_gunStrikeCoolTimer(0.f)
, x368_idleWanderDelayTimer(0.f)
, x36c_(1.f)
, x370_gunMotionSpeedMult(1.f)
, x374_(0.f)
, x378_shotSmokeStartTimer(0.f)
, x37c_rapidFireShotsDecayTimer(0.f)
, x380_shotSmokeTimer(0.f)
, x384_gunStrikeDelayTimer(0.f)
, x388_enterFreeLookDelayTimer(0.f)
, x38c_muzzleEffectVisTimer(0.f)
, x390_cooldown(0.f)
, x394_damageTimer(0.f)
, x398_damageAmt(0.f)
, x39c_phazonMorphT(0.f)
, x3a0_missileExitTimer(0.f)
, x3dc_damageLocation(CVector3f::Zero())
, x3e8_xf(CTransform4f::Identity())
, x418_beamLocalXf(CTransform4f::Identity())
, x448_elbowWorldXf(CTransform4f::Identity())
, x478_assistAimXf(CTransform4f::Identity())
, x4a8_gunWorldXf(CTransform4f::Identity())
, x4d8_gunLocalXf(CTransform4f::Identity())
, x508_elbowLocalXf(CTransform4f::Identity())
, x538_playerId(playerId)
, x53a_powerBomb(kInvalidUniqueId)
, x53c_lightId(kInvalidUniqueId)
, x550_camBob(CPlayerCameraBob::kCBT_One,
              CVector2f(CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY),
              CPlayerCameraBob::kCameraBobPeriod)
, x658_(1)
, x65c_(0.f)
, x660_(0.f)
, x664_(0.f)
, x668_aimVerticalSpeed(gpTweakPlayerGun->GetAimVerticalSpeed())
, x66c_aimHorizontalSpeed(gpTweakPlayerGun->GetAimHorizontalSpeed())
, x670_animSfx(InvalidSfxId, CSfxHandle())
, x678_morph(gpTweakPlayerGun->GetGunTransformTime(), gpTweakPlayerGun->GetHoloHoldTime())
, x6a0_motionState()
, x6c8_hologramClipCube(CVector3f(-0.29329199f, 0.f, -0.2481945f),
                        CVector3f(0.29329199f, 1.292392f, 0.2481945f))
, x6e0_rightHandModel(CAnimRes(gpTweakGunRes->xc_rightHand, CAnimRes::kDefaultCharIdx,
                               CVector3f(3.f, 3.f, 3.f), 0, true))
, x72c_currentBeam(nullptr)
, x730_outgoingBeam(nullptr)
, x734_loadingBeam(nullptr)
, x738_nextBeam(nullptr)
, x73c_gunMotion(rs_new CGunMotion(gpTweakGunRes->x4_gunMotion, kScaleVector))
, x740_grappleArm(rs_new CGrappleArm(kScaleVector))
, x744_auxWeapon(rs_new CAuxWeapon(playerId))
, x748_rainSplashGenerator(rs_new CRainSplashGenerator(kScaleVector, 20, 2, 0.f, 0.125f))
, x74c_powerBeam(
      rs_new CPowerBeam(gpTweakGunRes->x10_powerBeam, kWT_Power, playerId, kMT_Player, kScaleVector))
, x750_iceBeam(
      rs_new CIceBeam(gpTweakGunRes->x14_iceBeam, kWT_Ice, playerId, kMT_Player, kScaleVector))
, x754_waveBeam(
      rs_new CWaveBeam(gpTweakGunRes->x18_waveBeam, kWT_Wave, playerId, kMT_Player, kScaleVector))
, x758_plasmaBeam(rs_new CPlasmaBeam(gpTweakGunRes->x1c_plasmaBeam, kWT_Plasma, playerId, kMT_Player,
                                  kScaleVector))
, x75c_phazonBeam(rs_new CPhazonBeam(gpTweakGunRes->x20_phazonBeam, kWT_Phazon, playerId, kMT_Player,
                                  kScaleVector))
, x760_selectableBeams(nullptr)
, x774_holoTransitionGen(
      rs_new CElementGen(gpSimplePool->GetObj(SObjectTag('PART', gpTweakGunRes->x24_holoTransition))))
, x82c_shadow(rs_new CWorldShadow(32, 32, true))
, x830_chargeRumbleHandle(-1)
, x832_24_coolingCharge(false)
, x832_25_chargeEffectVisible(false)
, x832_26_comboFiring(false)
, x832_27_chargeAnimStarted(false)
, x832_28_readyForShot(false)
, x832_29_lockedOn(false)
, x832_30_requestReturnToDefault(false)
, x832_31_inRestPose(true)
, x833_24_notFidgeting(true)
, x833_25_(false)
, x833_26_(false)
, x833_27_(false)
, x833_28_phazonBeamActive(false)
, x833_29_pointBlankWorldSurface(false)
, x833_30_canShowAuxMuzzleEffect(true)
, x833_31_inFreeLook(false)
, x834_24_charging(false)
, x834_25_gunMotionFidgeting(false)
, x834_26_animPlaying(false)
, x834_27_underwater(false)
, x834_28_requestImmediateRecharge(false)
, x834_29_frozen(false)
, x834_30_inBigStrike(false)
, x834_31_gunMotionInFidgetBasePosition(false)
, x835_24_canFirePhazon(false)
, x835_25_inPhazonBeam(false)
, x835_26_phazonBeamMorphing(false)
, x835_27_intoPhazonBeam(false)
, x835_28_bombReady(false)
, x835_29_powerBombReady(false)
, x835_30_inPhazonPool(false)
, x835_31_actorAttached(false) {

  x6e0_rightHandModel.SetSortThermal(true);
  kVerticalAngleTable[2] = gpTweakPlayerGun->GetUpLookAngle();
  kVerticalAngleTable[0] = gpTweakPlayerGun->GetDownLookAngle();
  kHorizontalAngleTable[1] = gpTweakPlayerGun->GetHorizontalSpread();
  kHorizontalAngleTable[2] = gpTweakPlayerGun->GetHighHorizontalSpread();
  kHorizontalAngleTable[0] = gpTweakPlayerGun->GetLowHorizontalSpread();
  kVerticalVarianceTable[1] = gpTweakPlayerGun->GetVerticalSpread();
  kVerticalVarianceTable[2] = gpTweakPlayerGun->GetHighVerticalSpread();
  kVerticalVarianceTable[0] = gpTweakPlayerGun->GetLowVerticalSpread();
  CMotionState::SetExtendDistance(gpTweakPlayerGun->GetGunExtendDistance());

  InitBeamData();
  InitBombData();
  InitMuzzleData();
  InitCTData();
  LoadHandAnimTokens();
  x550_camBob.SetPlayerVelocity(CVector3f::Zero());
  x550_camBob.SetBobMagnitude(0.f);
  x550_camBob.SetBobTimeScale(0.f);
}

CPlayerGun::~CPlayerGun() {}

void CPlayerGun::AddToRenderer(const CFrustumPlanes& frustum, const CStateManager&) const {
  rstl::optional_object< CModelData >& model = x72c_currentBeam->SolidModelData();
  if (model) {
    model->RenderParticles(frustum);
  }
}

void CPlayerGun::PreRender(CStateManager& mgr, const CFrustumPlanes& frustum,
                           const CVector3f& camPos) {
  const CPlayerState& playerState = *mgr.GetPlayerState();
  if (playerState.GetCurrentVisor() == CPlayerState::kPV_Scan) {
    return;
  }

  CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr);
  switch (activeVisor) {
  case CPlayerState::kPV_Thermal: {
    float rgb =
        CMath::Clamp(0.6f, 0.5f * x380_shotSmokeTimer + 0.6f - x378_shotSmokeStartTimer, 1.f);
    x0_lights.BuildConstantAmbientLighting(CColor(rgb, rgb, rgb, 1.f));
    break;
  }
  case CPlayerState::kPV_Combat: {
    CAABox aabb = x72c_currentBeam->GetBounds(CTransform4f::Translate(camPos) * x4a8_gunWorldXf);
    if (mgr.GetNextAreaId() != kInvalidAreaId) {
      x0_lights.SetFindShadowLight(true);
      x0_lights.SetShadowDynamicRangeThreshold(0.25f);
      x0_lights.BuildAreaLightList(mgr, mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()), aabb);
    }
    x0_lights.BuildDynamicLightList(mgr, aabb);
    if (x0_lights.HasShadowLight()) {
      if (x72c_currentBeam->IsLoaded()) {
        x82c_shadow->BuildLightShadowTexture(mgr, mgr.GetNextAreaId(),
                                             x0_lights.GetShadowLightIndex(), aabb, true, false);
      }
    } else {
      x82c_shadow->ResetBlur();
    }
    break;
  }
  default:
    break;
  }

  if (x740_grappleArm->GetActive()) {
    x740_grappleArm->PreRender(mgr, frustum, camPos);
  }

  if (x678_morph.GetGunState() != CGunMorph::kGS_OutWipeDone ||
      activeVisor == CPlayerState::kPV_XRay) {
    x6e0_rightHandModel.AnimationData()->PreRender();
  }

  if (x833_28_phazonBeamActive) {
    gpRender->AllocatePhazonSuitMaskTexture();
  }
}

void CPlayerGun::TouchModel(const CStateManager&) const {}

CVector3f CPlayerGun::ConvertToScreenSpace(const CVector3f& pos, const CGameCamera&) const {
  return pos;
}

void CPlayerGun::DrawArm(const CStateManager&, const CVector3f&, const CModelFlags&) const {}

void CPlayerGun::Render(const CStateManager&, const CVector3f&, const CModelFlags&) const {}

void CPlayerGun::GetLctrWithShake(CTransform4f& xfOut, const CModelData&, const rstl::string&, bool,
                                  bool) {}

void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool) {}

void CPlayerGun::Update(float, float, float, CStateManager&) {}

void CPlayerGun::ProcessInput(const CFinalInput&, CStateManager&) {}

void CPlayerGun::ProcessChargeState(int releasedStates, int pressedStates, CStateManager& mgr,
                                    float dt) {
  if ((releasedStates & 0x1) != 0) {
    ResetCharged(dt, mgr);
    return;
  }
  if ((pressedStates & 0x1) != 0) {
    if (x32c_chargePhase == kCP_NotCharging && (pressedStates & 0x1) != 0 &&
        x348_chargeCooldownTimer == 0.f && x832_28_readyForShot == 1) {
      UpdateNormalShotCycle(dt, mgr);
      x32c_chargePhase = kCP_ChargeRequested;
    }
  } else {
    const CPlayerState* state = mgr.GetPlayerState();
    if (state->HasPowerUp(CPlayerState::kIT_Missiles) && (pressedStates & 0x2) != 0) {
      if (x32c_chargePhase >= kCP_FxGrown) {
        if (state->HasPowerUp(mBeamComboArr[size_t(x310_currentBeam)]))
          ActivateCombo(mgr);
      } else if (x32c_chargePhase == kCP_NotCharging) {
        FireSecondary(dt, mgr);
      }
    }
  }
}

void CPlayerGun::ResetNormal(CStateManager& mgr) {
  Reset(mgr, false);
  x832_28_readyForShot = false;
}

void CPlayerGun::ResetCharged(float dt, CStateManager& mgr) {
  if (x832_26_comboFiring == true) {
    return;
  }

  if (x32c_chargePhase >= kCP_FxGrowing) {
    x833_30_canShowAuxMuzzleEffect = false;
    UpdateNormalShotCycle(dt, mgr);
    x832_24_coolingCharge = true;
    CancelCharge(mgr, true);
  } else if (x32c_chargePhase != kCP_NotCharging) {
    x320_currentAuxBeam = x310_currentBeam;
    x833_30_canShowAuxMuzzleEffect = true;
    x32c_chargePhase = kCP_ChargeDone;
  }
  StopChargeSound(mgr);
}

void CPlayerGun::ProcessNormalState(int releasedStates, int pressedStates, CStateManager& mgr,
                                    float dt) {
  if ((releasedStates & 0x1) != 0) {
    ResetNormal(mgr);
    return;
  }

  if ((pressedStates & 0x1) != 0 && x348_chargeCooldownTimer == 0.f &&
      x832_28_readyForShot == true) {
    UpdateNormalShotCycle(dt, mgr);
    return;
  }
  if ((pressedStates & 0x2) != 0) {
    FireSecondary(dt, mgr);
  }
}

bool CPlayerGun::ExitMissile() {
  if ((x2f8_stateFlags & 0x1) != 0x1) {
    if ((x2f8_stateFlags & 0x10) != 0x10 && x338_nextState != kNS_ExitMissile) {
      x338_nextState = kNS_ExitMissile;
      PlayAnim(NWeaponTypes::kGAT_FromMissile, false);
    }
    return false;
  }
  return true;
}

void CPlayerGun::UpdateNormalShotCycle(float, CStateManager&) {}

void CPlayerGun::FireSecondary(float, CStateManager&) {}

void CPlayerGun::DropBomb(CPlayerGun::EBWeapon, CStateManager&) {}

void CPlayerGun::ActivateCombo(CStateManager&) {}

void CPlayerGun::EnableChargeFx(CPlayerState::EChargeStage, CStateManager&) {}

void CPlayerGun::UpdateChargeState(float, CStateManager&) {}

void CPlayerGun::Reset(CStateManager& mgr, bool b1) {
  x72c_currentBeam->Reset(mgr);
  x832_25_chargeEffectVisible = false;
  x832_24_coolingCharge = false;
  x833_26_ = false;
  x348_chargeCooldownTimer = 0.f;
  SetGunLightActive(false, mgr);
  if ((x2f8_stateFlags & 0x10) != 0x10) {
    if (!b1 && (x2f8_stateFlags & 0x2) != 0x2) {
      if ((x2f8_stateFlags & 0x8) != 0x8) {
        x2f8_stateFlags |= 0x1;
        x2f8_stateFlags &= ~0x16;
      }
      x318_comboAmmoIdx = 0;
      x31c_missileMode = kMM_Inactive;
    }
  } else {
    x2f8_stateFlags &= ~0x7;
  }
}

void CPlayerGun::ResetCharge(CStateManager& mgr, bool resetBeam) {
  if (x32c_chargePhase != kCP_NotCharging)
    StopChargeSound(mgr);

  if ((x2f8_stateFlags & 0x8) != 0x8 && (x2f8_stateFlags & 0x10) != 0x10) {
    bool doResetBeam =
        mgr.GetPlayer()->GetMorphballTransitionState() == CPlayer::kMS_Morphed || resetBeam;
    if (x832_27_chargeAnimStarted || doResetBeam)
      PlayAnim(NWeaponTypes::kGAT_BasePosition, false);
    if (doResetBeam)
      x72c_currentBeam->EnableSecondaryFx(CGunWeapon::kSFT_None);
    if ((x2f8_stateFlags & 0x2) != 0x2 || x330_chargeState != kCS_Normal) {
      if ((x2f8_stateFlags & 0x8) != 0x8) {
        x2f8_stateFlags |= 0x1;
        x2f8_stateFlags &= ~0x16;
      }
      x318_comboAmmoIdx = 0;
      x31c_missileMode = kMM_Inactive;
    }
  }

  x32c_chargePhase = kCP_NotCharging;
  x330_chargeState = kCS_Normal;
  x320_currentAuxBeam = x310_currentBeam;
  x833_30_canShowAuxMuzzleEffect = true;
  x832_27_chargeAnimStarted = false;
  x832_26_comboFiring = false;
  x344_comboXferTimer = 0.f;
}

#define SFXwpn_morph_out_wipe 1774

void CPlayerGun::ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState,
                                 bool playSelectionSfx) {
  StopContinuousBeam(mgr, true);
  if (playerState.ItemEnabled(CPlayerState::kIT_ChargeBeam)) {
    ResetCharge(mgr, false);
  }
  const CAnimPlaybackParms parms(mHandAnimId[size_t(x314_nextBeam)], -1, 1.f, true);
  x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false);
  Reset(mgr, false);
  if (playSelectionSfx) {
    CSfxManager::SfxStart(SFXwpn_morph_out_wipe, 0x7f, 0x40, true, CSfxManager::kMaxPriority, false,
                          CSfxManager::kAllAreas);
  }
  x2ec_lastFireButtonStates &= ~0x1;
  x320_currentAuxBeam = x310_currentBeam;
  x833_30_canShowAuxMuzzleEffect = true;
}

void CPlayerGun::ChangeWeapon(const CPlayerState&, CStateManager&) {}

void CPlayerGun::StartPhazonBeamTransition(bool, CStateManager&, CPlayerState&) {}

void CPlayerGun::HandleWeaponChange(const CFinalInput&, CStateManager&) {}

void CPlayerGun::HandleBeamChange(const CFinalInput&, CStateManager&) {}

void CPlayerGun::SetPhazonBeamMorph(bool) {}

void CPlayerGun::HandlePhazonBeamChange(CStateManager&) {}

void CPlayerGun::InitBeamData() {
  x760_selectableBeams[0] = x74c_powerBeam.get();
  x760_selectableBeams[1] = x750_iceBeam.get();
  x760_selectableBeams[2] = x754_waveBeam.get();
  x760_selectableBeams[3] = x758_plasmaBeam.get();
  x72c_currentBeam = x760_selectableBeams[0];
  x738_nextBeam = x72c_currentBeam;
  x774_holoTransitionGen->SetParticleEmission(true);
}

void CPlayerGun::InitBombData() {
  for (int i = 0; i < 2; ++i)
    x784_bombEffects.push_back(rstl::reserved_vector< TLockedToken< CGenDescription >, 2 >());

  CToken obj1 = gpSimplePool->GetObj(SObjectTag('PART', gpTweakGunRes->x28_bombSet));
  CToken obj2 = gpSimplePool->GetObj(SObjectTag('PART', gpTweakGunRes->x2c_bombExplode));
  CToken obj3 = gpSimplePool->GetObj(SObjectTag('PART', gpTweakGunRes->x30_powerBombExplode));

  x784_bombEffects[0].push_back(obj1);
  x784_bombEffects[0].push_back(obj2);
  x784_bombEffects[1].push_back(obj3);
  x784_bombEffects[1].push_back(obj3);
}

void CPlayerGun::InitMuzzleData() {
  for (int i = 0; i < 5; ++i) {
    SObjectTag tag('PART', (i < 0 || 4 < i) ? kInvalidAssetId : gpTweakGunRes->xa4_auxMuzzle[i]);
    x7c0_auxMuzzleEffects.push_back(gpSimplePool->GetObj(tag));
    // TODO: not likely correct, maybe need improvements to auto_ptr
    x800_auxMuzzleGenerators.push_back(rs_new CElementGen(x7c0_auxMuzzleEffects.back()));
    x800_auxMuzzleGenerators.back()->SetParticleEmission(false);
  }
}

void CPlayerGun::InitCTData() { x77c_comboXferGen = rstl::auto_ptr< CElementGen >(); }

float CPlayerGun::GetBeamVelocity() const {
  if (x72c_currentBeam->IsLoaded())
    return x72c_currentBeam->GetVelocityInfo().GetVelocity(int(x330_chargeState)).GetY();
  return 10.f;
}

TUniqueId CPlayerGun::GetTargetId(CStateManager& mgr) {
  TUniqueId ret = mgr.GetPlayer()->GetOrbitTargetId();
  if (x832_26_comboFiring && ret == kInvalidUniqueId && x310_currentBeam == CPlayerState::kBI_Wave)
    ret = mgr.GetPlayer()->GetOrbitNextTargetId();

  if (ret != kInvalidUniqueId) {
    const CActor* act = TCastToConstPtr< CActor >(mgr.GetObjectById(ret));
    if (act != nullptr) {
      if (!act->GetMaterialList().HasMaterial(kMT_Target)) {
        ret = kInvalidUniqueId;
      }
    }
  }

  return ret;
}

CPlayerGun::CGunMorph::CGunMorph(float gunTransformTime, float holoHoldTime)
: x0_yLerp(0.f)
, x4_gunTransformTime(CMath::Sign(gunTransformTime))
, x8_remTime(0.f)
, xc_speed(0.1f)
, x10_holoHoldTime(fabs(holoHoldTime))
, x14_remHoldTime(2.f)
, x18_transitionFactor(1.f)
, x1c_dir(kD_Done)
, x20_gunState(kGS_OutWipeDone)
, x24_24_morphing(false)
, x24_25_weaponChanged(false) {}

void CPlayerGun::CGunMorph::StartWipe(CPlayerGun::CGunMorph::EDir dir) {
  x14_remHoldTime = x10_holoHoldTime;
  if (dir == kD_In && x20_gunState == kGS_InWipeDone)
    return;

  if (x1c_dir != dir && x20_gunState != kGS_OutWipe) {
    x8_remTime = x4_gunTransformTime;
    xc_speed = 1.f / x4_gunTransformTime;
  } else if (x20_gunState != kGS_InWipe) {
    x8_remTime = x4_gunTransformTime - x8_remTime;
  }

  x1c_dir = dir;
  x20_gunState = x1c_dir == kD_In ? kGS_InWipe : kGS_OutWipe;
  x24_24_morphing = true;
}

CPlayerGun::CGunMorph::EMorphEvent CPlayerGun::CGunMorph::Update(float inY, float outY, float dt) {
  EMorphEvent ret = kME_None;

  switch (x20_gunState) {
  case kGS_InWipeDone:
    x14_remHoldTime -= dt;
    if (x14_remHoldTime <= 0.f && x24_25_weaponChanged) {
      StartWipe(kD_Out);
      x24_25_weaponChanged = false;
      x14_remHoldTime = 0.f;
      ret = kME_InWipeDone;
    }
    // explicitly no break

  case kGS_OutWipeDone:
  case kGS_InWipe:
  case kGS_OutWipe:
  default:
    if (x24_24_morphing) {
      float omt = x8_remTime * xc_speed;
      float t = 1.f - omt;
      if (x1c_dir == kD_In) {
        x0_yLerp = omt * outY + t * inY;
        x18_transitionFactor = omt;
      } else {
        x0_yLerp = omt * inY + t * outY;
        x18_transitionFactor = t;
      }

      if (x8_remTime <= 0.f) {
        x24_24_morphing = false;
        x8_remTime = 0.f;
        if (x1c_dir == kD_In) {
          x20_gunState = kGS_InWipeDone;
          x18_transitionFactor = 0.f;
        } else {
          x18_transitionFactor = 1.f;
          x20_gunState = kGS_OutWipeDone;
          x1c_dir = kD_Done;
          ret = kME_OutWipeDone;
        }
      } else {
        x8_remTime -= dt;
      }
    }
  }

  return ret;
}

void CPlayerGun::UpdateWeaponFire(float dt, CPlayerState& playerState, CStateManager& mgr) {
  uint oldFiring = x2ec_lastFireButtonStates;
  x2ec_lastFireButtonStates = x2f4_fireButtonStates;
  uint pressedStates = x2f4_fireButtonStates & (oldFiring ^ x2f4_fireButtonStates);
  x2f0_pressedFireButtonStates = pressedStates;
  uint releasedStates = oldFiring & (oldFiring ^ x2f4_fireButtonStates);
  x832_28_readyForShot = false;

  CPlayer& player = *mgr.Player();
  if (!x832_24_coolingCharge && !x834_30_inBigStrike) {
    float coolDown = x72c_currentBeam->GetWeaponInfo().x0_coolDown;
    if ((pressedStates & 0x1) == 0) {
      if (x390_cooldown >= coolDown) {
        x390_cooldown = coolDown;
        if (player.GetMorphballTransitionState() == CPlayer::kMS_Unmorphed &&
            playerState.ItemEnabled(CPlayerState::kIT_ChargeBeam) &&
            player.GetGunHolsterState() == CPlayer::kGH_Drawn &&
            player.GetGrappleState() == CPlayer::kGS_None &&
            playerState.GetTransitioningVisor() != CPlayerState::kPV_Scan &&
            playerState.GetCurrentVisor() != CPlayerState::kPV_Scan &&
            (x2ec_lastFireButtonStates & 0x1) != 0 && x32c_chargePhase == kCP_NotCharging) {
          x832_28_readyForShot = true;
          pressedStates |= 0x1;
          x390_cooldown = 0.f;
        }
      }
    } else if (x390_cooldown >= coolDown) {
      x832_28_readyForShot = true;
      x390_cooldown = 0.f;
    }
    x390_cooldown += dt;
  }

  if (x834_28_requestImmediateRecharge)
    x834_28_requestImmediateRecharge = (x2ec_lastFireButtonStates & 0x1) != 0;

  if (player.GetMorphballTransitionState() == CPlayer::kMS_Morphed) {
    x835_28_bombReady = false;
    x835_29_powerBombReady = false;
    if (!x835_31_actorAttached) {
      x835_28_bombReady = true;
      if (x53a_powerBomb != kInvalidUniqueId &&
          !mgr.CanCreateProjectile(x538_playerId, kWT_PowerBomb, 1)) {
        const CPowerBomb* pb = static_cast< const CPowerBomb* >(mgr.GetObjectById(x53a_powerBomb));
        if (pb && !pb->IsEnding()) {
          x835_28_bombReady = false;
        } else {
          x53a_powerBomb = kInvalidUniqueId;
        }
      }
      if (((pressedStates & 0x1) != 0 || x32c_chargePhase != kCP_NotCharging) &&
          playerState.HasPowerUp(CPlayerState::kIT_MorphBallBombs)) {
        if (x835_28_bombReady)
          DropBomb(kBW_Bomb, mgr);
      } else if (playerState.HasPowerUp(CPlayerState::kIT_PowerBombs) &&
                 playerState.GetItemAmount(CPlayerState::kIT_PowerBombs) > 0) {
        x835_29_powerBombReady = mgr.CanCreateProjectile(x538_playerId, kWT_PowerBomb, 1) &&
                                 mgr.CanCreateProjectile(x538_playerId, kWT_Bomb, 1);
        if ((pressedStates & 0x2) != 0 && x835_29_powerBombReady)
          DropBomb(kBW_PowerBomb, mgr);
      }
    }
  } else if ((x2f8_stateFlags & 0x8) != 0x8 &&
             player.GetMorphballTransitionState() == CPlayer::kMS_Unmorphed) {
    if ((pressedStates & 0x2) != 0 && x318_comboAmmoIdx == 0 && (x2f8_stateFlags & 0x2) != 0x2 &&
        x32c_chargePhase == kCP_NotCharging) {
      uint missileCount = playerState.GetItemAmount(CPlayerState::kIT_Missiles);
      if (x338_nextState != kNS_EnterMissile && x338_nextState != kNS_ExitMissile) {
        if (playerState.HasPowerUp(CPlayerState::kIT_Missiles) && missileCount > 0) {
          x300_remainingMissiles = missileCount;
          if (x300_remainingMissiles > 5)
            x300_remainingMissiles = 5;
          if (!x835_25_inPhazonBeam) {
            x2f8_stateFlags &= ~0x1;
            x2f8_stateFlags |= 0x6;
            x318_comboAmmoIdx = 1;
            x31c_missileMode = kMM_Active;
          }
          FireSecondary(dt, mgr);
        } else {
          if (!CSfxManager::IsPlaying(x2e4_invalidSfx)) {
            x2e4_invalidSfx =
                NWeaponTypes::play_sfx(SFXwpn_invalid_action, x834_27_underwater, false, 0x4a);
          } else {
            x2e4_invalidSfx.Clear();
          }
        }
      }
    } else {
      if (x3a4_fidget.GetState() == CFidget::kS_NoFidget) {
        if ((x2f8_stateFlags & 0x10) == 0x10 && x744_auxWeapon->IsComboFxActive(mgr)) {
          if (x2ec_lastFireButtonStates == 0 ||
              (x310_currentBeam == CPlayerState::kBI_Wave && x833_29_pointBlankWorldSurface)) {
            StopContinuousBeam(mgr, (x2f8_stateFlags & 0x8) == 0x8);
          }
        } else {
          if (mgr.GetPlayerState()->ItemEnabled(CPlayerState::kIT_ChargeBeam) &&
              x33c_phazonBeamState == kPBS_Inactive)
            ProcessChargeState(releasedStates, pressedStates, mgr, dt);
          else
            ProcessNormalState(releasedStates, pressedStates, mgr, dt);
        }
      }
    }
  }
}

void CPlayerGun::ResetIdle(CStateManager& mgr) {
  CFidget::EState fidgetState = x3a4_fidget.GetState();
  x370_gunMotionSpeedMult = 1.f;
  x550_camBob.SetState(CPlayerCameraBob::kCBS_GunFireNoBob, mgr);
  if (fidgetState != CFidget::kS_NoFidget) {
    if (fidgetState == CFidget::kS_Loading) {
      UnLoadFidget();
    }
    ReturnArmAndGunToDefault(mgr, true);
  }
  x3a4_fidget.ResetAll();
  ReturnToRestPose();
  if (x324_idleState != kIS_NotIdle)
    x324_idleState = kIS_NotIdle;
  if (!x740_grappleArm->GetActive())
    x834_26_animPlaying = false;
}

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 firing, float dt, CTransform4f& xf, CStateManager& mgr) {
  if (firing) {
    x24_fireState = kFS_StartFire;
    x8_fireTime = 0.f;
  } else if (x24_fireState != kFS_NotFiring) {
    if (x8_fireTime > dt)
      x24_fireState = kFS_Firing;
    x8_fireTime += dt;
  }

  if (x0_24_extendParabola && x20_state == kMS_LockOn) {
    float extendT = xc_curExtendDist * (1.0f / gGunExtendDistance);
    CTransform4f other =
        CTransform4f::RotateZ(CRelAngle::FromDegrees(extendT * -4.f * (extendT - 1.f) * 15.f));
    other.SetTranslation(CVector3f(0.f, xc_curExtendDist, 0.f));
    xf = xf * other;
  } else if (x24_fireState == kFS_StartFire || x24_fireState == kFS_Firing) {
    if (fabs(x14_rotationT - 1.f) < 0.1f) {
      x18_startRotation = x1c_endRotation;
      x14_rotationT = 0.f;
      if (x24_fireState == kFS_StartFire) {
        x1c_endRotation = mgr.Random()->Next() % 15;
        x1c_endRotation *= (mgr.Random()->Next() % 100) > 45 ? 1.f : -1.f;
      } else {
        x1c_endRotation = 0.f;
        if (x18_startRotation == x1c_endRotation) {
          x10_curRotation = x1c_endRotation;
          x24_fireState = kFS_NotFiring;
        }
      }
    } else {
      x10_curRotation = (x1c_endRotation - x18_startRotation) * x14_rotationT + x18_startRotation;
    }

    x14_rotationT += (1.f - x14_rotationT) * 0.8f * (10.f * dt);

    CQuaternion quat = CQuaternion::AxisAngle(CUnitVector3f(xf.GetForward()),
                                              CRelAngle::FromDegrees(x10_curRotation));

    CTransform4f tmpXf = quat.BuildTransform4f() * xf.GetRotation();
    tmpXf.SetTranslation(xf.GetTranslation());
    xf = tmpXf * CTransform4f::Translate(0.f, xc_curExtendDist, 0.f);
  } else {
    xf = xf * CTransform4f::Translate(0.f, xc_curExtendDist, 0.f);
  }

  switch (x20_state) {
  case kMS_LockOn:
    xc_curExtendDist += 3.f * dt;
    if (xc_curExtendDist > gGunExtendDistance) {
      xc_curExtendDist = gGunExtendDistance;
      x20_state = kMS_One;
      x0_24_extendParabola = false;
    }
    break;
  case kMS_CancelLockOn:
    xc_curExtendDist -= 3.f * dt;
    if (xc_curExtendDist < 0.f) {
      xc_curExtendDist = 0.f;
      x20_state = kMS_Zero;
    }
    break;
  default:
    break;
  }

  if (x0_24_extendParabola != true) {
    if (x4_extendParabolaDelayTimer < 30.f) {
      x4_extendParabolaDelayTimer += dt;
    } else {
      x0_24_extendParabola = true;
      x4_extendParabolaDelayTimer = 0.f;
    }
  }
}

void CPlayerGun::DamageRumble(const CVector3f&, float damage, const CStateManager&) {}

void CPlayerGun::TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr) {
  const CPlayer& player = *mgr.GetPlayer();
  bool hasStrikeAngle = false;
  float angle = 0.f;
  if (x398_damageAmt >= 10.f && !bigStrike && (x2f8_stateFlags & 0x10) != 0x10 &&
      !x832_26_comboFiring && x384_gunStrikeDelayTimer <= 0.f) {
    x384_gunStrikeDelayTimer = 20.f;
    x364_gunStrikeCoolTimer = 0.75f;
    if (x678_morph.GetGunState() == CGunMorph::kGS_OutWipeDone) {
      CVector3f localDamageLoc = player.GetTransform().TransposeRotate(x3dc_damageLocation);
      angle =
          CAbsAngle::FromRadians(atan2(localDamageLoc.GetY(), localDamageLoc.GetX())).AsDegrees();
      hasStrikeAngle = true;
    }
  }

  if (hasStrikeAngle || bigStrike) {
    if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::kPV_Scan) {
      x73c_gunMotion->PlayPasAnim(SamusGun::kAS_Struck, mgr, angle, bigStrike);
      if ((bigStrike && notFromMetroid) || x833_31_inFreeLook)
        x740_grappleArm->EnterStruck(mgr, angle, bigStrike, !x833_31_inFreeLook);
    }
  }

  x398_damageAmt = 0.f;
  x3dc_damageLocation = CVector3f::Zero();
}

void CPlayerGun::StopChargeSound(CStateManager&) {}

void CPlayerGun::CancelFiring(CStateManager&) {}

void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) {}

void CPlayerGun::StopContinuousBeam(CStateManager&, bool) {}

void CPlayerGun::RenderEnergyDrainEffects(const CStateManager&) const {}

void CPlayerGun::DoUserAnimEvents(float, CStateManager&) {}

void CPlayerGun::DoUserAnimEvent(float, CStateManager&, const CInt32POINode&, EUserEventType) {}

void CPlayerGun::CancelCharge(CStateManager&, bool) {}

void CPlayerGun::EnterFreeLook(CStateManager&) {}

void CPlayerGun::EnterFidget(CStateManager&) {}

void CPlayerGun::UpdateLeftArmTransform(const CModelData&, const CStateManager&) {}

void CPlayerGun::ReturnArmAndGunToDefault(CStateManager&, bool) {}

void CPlayerGun::UpdateAuxWeapons(float, const CTransform4f&, CStateManager&) {}

void CPlayerGun::CancelLockOn() {}

void CPlayerGun::CreateGunLight(CStateManager&) {}

void CPlayerGun::DeleteGunLight(CStateManager&) {}

void CPlayerGun::UpdateGunLight(const CTransform4f&, CStateManager&) {}

void CPlayerGun::SetGunLightActive(bool, CStateManager&) {}

void CPlayerGun::LoadHandAnimTokens() {}

void CPlayerGun::ProcessPhazonGunMorph(float, CStateManager&) {}

void CPlayerGun::ProcessGunMorph(float, CStateManager&) {}

void CPlayerGun::AsyncLoadFidget(CStateManager&) {}

void CPlayerGun::UnLoadFidget() {}

bool CPlayerGun::IsFidgetLoaded() { return false; }

void CPlayerGun::SetFidgetAnimBits(int, bool) {}

void CPlayerGun::AsyncLoadSuit(CStateManager&) {}

void CPlayerGun::ReturnToRestPose() {}

TUniqueId CPlayerGun::DropPowerBomb(CStateManager&) const {}

void CPlayerGun::SetPhazonBeamFeedback(bool) {}
