metaforce/Runtime/Weapon/CPlayerGun.cpp

1223 lines
38 KiB
C++
Raw Normal View History

2017-08-25 06:18:09 +00:00
#include "TCastTo.hpp"
#include "CPlayerGun.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "Character/CPrimitive.hpp"
2017-08-25 06:18:09 +00:00
#include "World/CPlayer.hpp"
#include "CEnergyProjectile.hpp"
#include "MP1/World/CMetroid.hpp"
#include "World/CScriptWater.hpp"
#include "World/CGameLight.hpp"
#include "Input/ControlMapper.hpp"
namespace urde
{
static const zeus::CVector3f sGunScale(2.f);
static float kVerticalAngleTable[] = { -30.f, 0.f, 30.f };
static float kHorizontalAngleTable[] = { 30.f, 30.f, 30.f };
static float kVerticalVarianceTable[] = { 30.f, 30.f, 30.f };
float CPlayerGun::CMotionState::gGunExtendDistance = 0.125f;
CPlayerGun::CPlayerGun(TUniqueId playerId)
2017-08-25 06:18:09 +00:00
: x0_lights(8, zeus::CVector3f{-30.f, 0.f, 30.f}, 4, 4, 0, 0, 0, 0.1f), x538_playerId(playerId),
x550_camBob(CPlayerCameraBob::ECameraBobType::One,
zeus::CVector2f(CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY),
CPlayerCameraBob::kCameraBobPeriod),
x678_morph(g_tweakPlayerGun->GetGunTransformTime(), g_tweakPlayerGun->GetHoloHoldTime()),
x6c8_(zeus::CVector3f(-0.29329199f, 0.f, -0.2481945f),
zeus::CVector3f(0.29329199f, 1.292392f, 0.2481945f)),
x6e0_rightHandModel(CAnimRes(g_tweakGunRes->xc_rightHand, 0, zeus::CVector3f(3.f), 0, true))
{
x354_bombFuseTime = g_tweakPlayerGun->GetBombFuseTime();
x358_bombDropDelayTime = g_tweakPlayerGun->GetBombDropDelayTime();
x668_aimVerticalSpeed = g_tweakPlayerGun->GetAimVerticalSpeed();
x66c_aimHorizontalSpeed = g_tweakPlayerGun->GetAimHorizontalSpeed();
x73c_gunMotion = std::make_unique<CGunMotion>(g_tweakGunRes->x4_gunMotion, sGunScale);
x740_grappleArm = std::make_unique<CGrappleArm>(sGunScale);
x744_auxWeapon = std::make_unique<CAuxWeapon>(playerId);
x748_rainSplashGenerator = std::make_unique<CRainSplashGenerator>(sGunScale, 20, 2, 0.f, 0.125f);
x74c_powerBeam = std::make_unique<CPowerBeam>(g_tweakGunRes->x10_powerBeam, EWeaponType::Power,
playerId, EMaterialTypes::Player, sGunScale);
x750_iceBeam = std::make_unique<CIceBeam>(g_tweakGunRes->x14_iceBeam, EWeaponType::Ice,
playerId, EMaterialTypes::Player, sGunScale);
x754_waveBeam = std::make_unique<CWaveBeam>(g_tweakGunRes->x18_waveBeam, EWeaponType::Wave,
playerId, EMaterialTypes::Player, sGunScale);
x758_plasmaBeam = std::make_unique<CPlasmaBeam>(g_tweakGunRes->x1c_plasmaBeam, EWeaponType::Plasma,
playerId, EMaterialTypes::Player, sGunScale);
x75c_phazonBeam = std::make_unique<CPhazonBeam>(g_tweakGunRes->x20_phazonBeam, EWeaponType::Phazon,
playerId, EMaterialTypes::Player, sGunScale);
x774_holoTransitionGen = std::make_unique<CElementGen>(
g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x24_holoTransition}),
CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One);
x82c_shadow = std::make_unique<CWorldShadow>(32, 32, true);
x832_31_ = true;
2017-07-20 06:04:40 +00:00
x833_24_isFidgeting = true;
x833_30_ = true;
x6e0_rightHandModel.SetSortThermal(true);
kVerticalAngleTable[2] = g_tweakPlayerGun->GetUpLookAngle();
kVerticalAngleTable[0] = g_tweakPlayerGun->GetDownLookAngle();
kHorizontalAngleTable[1] = g_tweakPlayerGun->GetHorizontalSpread();
kHorizontalAngleTable[2] = g_tweakPlayerGun->GetHighHorizontalSpread();
kHorizontalAngleTable[0] = g_tweakPlayerGun->GetLowHorizontalSpread();
kVerticalVarianceTable[1] = g_tweakPlayerGun->GetVerticalSpread();
kVerticalVarianceTable[2] = g_tweakPlayerGun->GetHighVerticalSpread();
kVerticalVarianceTable[0] = g_tweakPlayerGun->GetLowVerticalSpread();
CMotionState::SetExtendDistance(g_tweakPlayerGun->GetGunExtendDistance());
InitBeamData();
InitBombData();
InitMuzzleData();
InitCTData();
LoadHandAnimTokens();
x550_camBob.SetPlayerVelocity(zeus::CVector3f::skZero);
x550_camBob.SetBobMagnitude(0.f);
x550_camBob.SetBobTimeScale(0.f);
}
void CPlayerGun::InitBeamData()
{
x760_selectableBeams[0] = x74c_powerBeam.get();
x760_selectableBeams[0] = x750_iceBeam.get();
x760_selectableBeams[0] = x754_waveBeam.get();
x760_selectableBeams[0] = x758_plasmaBeam.get();
x72c_currentBeam = x760_selectableBeams[0];
x738_nextBeam = x72c_currentBeam;
x774_holoTransitionGen->SetParticleEmission(true);
}
void CPlayerGun::InitBombData()
{
x784_bombEffects.resize(2);
x784_bombEffects[0].push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x28_bombSet}));
x784_bombEffects[0].push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x2c_bombExplode}));
TLockedToken<CGenDescription> pbExplode =
g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x30_powerBombExplode});
x784_bombEffects[1].push_back(pbExplode);
x784_bombEffects[1].push_back(pbExplode);
}
void CPlayerGun::InitMuzzleData()
{
for (int i=0 ; i<5 ; ++i)
{
x7c0_auxMuzzleEffects.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'),
g_tweakGunRes->xa4_auxMuzzle[i]}));
x800_auxMuzzleGenerators.emplace_back(new CElementGen(x7c0_auxMuzzleEffects.back(),
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One));
x800_auxMuzzleGenerators.back()->SetParticleEmission(false);
}
}
void CPlayerGun::InitCTData()
{
x77c_.reset();
}
void CPlayerGun::LoadHandAnimTokens()
{
std::set<CPrimitive> prims;
for (int i=0 ; i<3 ; ++i)
{
CAnimPlaybackParms parms(i, -1, 1.f, true);
x6e0_rightHandModel.GetAnimationData()->GetAnimationPrimitives(parms, prims);
}
CAnimData::PrimitiveSetToTokenVector(prims, x540_handAnimTokens, true);
}
2017-08-26 04:36:25 +00:00
void CPlayerGun::TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr)
2017-06-12 04:23:34 +00:00
{
2017-08-25 06:18:09 +00:00
bool hasAngle = false;
float angle = 0.f;
2017-08-26 04:36:25 +00:00
if (x398_damageAmt >= 10.f && !bigStrike && (x2f8_ & 0x10) != 0x10 && !x832_26_ && x384_ <= 0.f)
2017-08-25 06:18:09 +00:00
{
x384_ = 20.f;
x364_ = 0.75f;
if (x678_morph.GetGunState() == CGunMorph::EGunState::One)
{
zeus::CVector3f localDamageLoc = mgr.GetPlayer().GetTransform().transposeRotate(x3dc_damageLocation);
angle = zeus::CRelAngle(std::atan2(localDamageLoc.y, localDamageLoc.x)).asDegrees();
hasAngle = true;
}
}
2017-06-12 04:23:34 +00:00
2017-08-26 04:36:25 +00:00
if (hasAngle || bigStrike)
2017-08-25 06:18:09 +00:00
{
if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan)
{
2017-08-26 04:36:25 +00:00
x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Struck, mgr, angle, bigStrike);
if ((bigStrike && notFromMetroid) || x833_31_)
x740_grappleArm->EnterStruck(mgr, angle, bigStrike, !x833_31_);
2017-08-25 06:18:09 +00:00
}
}
x398_damageAmt = 0.f;
x3dc_damageLocation = zeus::CVector3f::skZero;
}
void CPlayerGun::CreateGunLight(CStateManager& mgr)
{
if (x53c_lightId != kInvalidUniqueId)
return;
x53c_lightId = mgr.AllocateUniqueId();
CGameLight* light = new CGameLight(x53c_lightId, kInvalidAreaId, false, "GunLite", x3e8_xf, x538_playerId,
CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skBlack),
x53c_lightId.Value(), 0, 0.f);
mgr.AddObject(light);
}
void CPlayerGun::DeleteGunLight(CStateManager& mgr)
{
if (x53c_lightId == kInvalidUniqueId)
return;
mgr.FreeScriptObject(x53c_lightId);
x53c_lightId = kInvalidUniqueId;
}
2017-08-26 04:36:25 +00:00
void CPlayerGun::UpdateGunLight(const zeus::CTransform& pos, CStateManager& mgr)
{
}
2017-08-25 06:18:09 +00:00
void CPlayerGun::SetGunLightActive(bool active, CStateManager& mgr)
{
if (x53c_lightId == kInvalidUniqueId)
return;
if (TCastToPtr<CGameLight> light = mgr.ObjectById(x53c_lightId))
{
light->SetActive(active);
if (active)
{
if (CElementGen* gen = x72c_currentBeam->GetChargeMuzzleFx())
{
if (gen->SystemHasLight())
{
CLight genLight = gen->GetLight();
genLight.SetColor(zeus::CColor::skBlack);
light->SetLight(genLight);
}
}
}
}
}
static const u32 skBeamIdMap[] = { 0, 1, 2, 3, 0 };
static const u32 skBeamAnimIds[] = { 0, 1, 2, 1 };
void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr)
{
const CPlayer& player = mgr.GetPlayer();
bool isUnmorphed = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed;
switch (msg)
{
case EScriptObjectMessage::Registered:
{
CreateGunLight(mgr);
x320_ = x314_pendingSelectedBeam = x310_selectedBeam =
skBeamIdMap[int(mgr.GetPlayerState()->GetCurrentBeam())];
x72c_currentBeam = x738_nextBeam = x760_selectableBeams[x310_selectedBeam];
x72c_currentBeam->Load(mgr, true);
x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get());
x744_auxWeapon->Load(x310_selectedBeam, mgr);
CAnimPlaybackParms parms(skBeamAnimIds[int(mgr.GetPlayerState()->GetCurrentBeam())], -1, 1.f, true);
x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false);
break;
}
case EScriptObjectMessage::Deleted:
DeleteGunLight(mgr);
break;
case EScriptObjectMessage::UpdateSplashInhabitant:
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed)
{
if (TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(sender))
{
if (water->GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::PhazonFluid)
{
x835_24_canFirePhazon = true;
x835_25_inPhazonBeam = true;
}
}
}
if (player.GetDistanceUnderWater() > player.GetEyeHeight())
{
x834_27_underwater = true;
if (x744_auxWeapon->IsComboFxActive(mgr) && x310_selectedBeam != 2)
StopContinuousBeam(mgr, false);
}
else
{
x834_27_underwater = false;
}
break;
case EScriptObjectMessage::RemoveSplashInhabitant:
x834_27_underwater = false;
x835_24_canFirePhazon = false;
break;
case EScriptObjectMessage::AddPhazonPoolInhabitant:
x835_30_inPhazonPool = true;
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed)
x835_24_canFirePhazon = true;
break;
case EScriptObjectMessage::UpdatePhazonPoolInhabitant:
x835_30_inPhazonPool = true;
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed)
{
x835_24_canFirePhazon = true;
x835_25_inPhazonBeam = true;
if (x833_28_phazonBeamActive && static_cast<CPhazonBeam*>(x72c_currentBeam)->IsFiring())
if (TCastToPtr<CEntity> ent = mgr.ObjectById(sender))
mgr.SendScriptMsg(ent.GetPtr(), x538_playerId, EScriptObjectMessage::Decrement);
}
break;
case EScriptObjectMessage::RemovePhazonPoolInhabitant:
x835_30_inPhazonPool = false;
x835_24_canFirePhazon = false;
break;
case EScriptObjectMessage::Damage:
{
2017-08-26 04:36:25 +00:00
bool bigStrike = false;
2017-08-25 06:18:09 +00:00
bool metroidAttached = false;
if (TCastToConstPtr<CEnergyProjectile> proj = mgr.GetObjectById(sender))
{
2017-08-26 04:36:25 +00:00
if ((proj->GetAttribField() & CGameProjectile::EProjectileAttrib::BigStrike) !=
2017-08-25 06:18:09 +00:00
CGameProjectile::EProjectileAttrib::None)
{
x394_damageTimer = proj->GetDamageDuration();
2017-08-26 04:36:25 +00:00
bigStrike = true;
2017-08-25 06:18:09 +00:00
}
}
else if (TCastToConstPtr<CPatterned> ai = mgr.GetObjectById(sender))
{
if (ai->GetX402_28())
{
x394_damageTimer = ai->GetDamageDuration();
2017-08-26 04:36:25 +00:00
bigStrike = true;
2017-08-25 06:18:09 +00:00
if (player.GetAttachedActor() != kInvalidUniqueId)
metroidAttached = CPatterned::CastTo<MP1::CMetroid>(
mgr.GetObjectById(player.GetAttachedActor())) != nullptr;
}
}
2017-08-26 04:36:25 +00:00
if (!x834_30_inBigStrike)
2017-08-25 06:18:09 +00:00
{
2017-08-26 04:36:25 +00:00
if (bigStrike)
2017-08-25 06:18:09 +00:00
{
x834_31_ = false;
CancelFiring(mgr);
}
2017-08-26 04:36:25 +00:00
TakeDamage(bigStrike, !metroidAttached, mgr);
x834_30_inBigStrike = bigStrike;
2017-08-25 06:18:09 +00:00
}
break;
}
case EScriptObjectMessage::OnFloor:
2017-08-26 04:36:25 +00:00
if (player.GetControlsFrozen() && !x834_30_inBigStrike)
2017-08-25 06:18:09 +00:00
{
x2f4_ = 0;
x2ec_firing = 0;
CancelFiring(mgr);
TakeDamage(true, false, mgr);
x394_damageTimer = 0.75f;
2017-08-26 04:36:25 +00:00
x834_30_inBigStrike = true;
2017-08-25 06:18:09 +00:00
}
break;
default:
break;
}
x740_grappleArm->AcceptScriptMsg(msg, sender, mgr);
x758_plasmaBeam->AcceptScriptMsg(msg, sender, mgr);
x75c_phazonBeam->AcceptScriptMsg(msg, sender, mgr);
x744_auxWeapon->AcceptScriptMsg(msg, sender, mgr);
2017-06-12 04:23:34 +00:00
}
void CPlayerGun::AsyncLoadSuit(CStateManager& mgr)
{
x72c_currentBeam->AsyncLoadSuitArm(mgr);
x740_grappleArm->AsyncLoadSuit(mgr);
}
2017-08-25 06:18:09 +00:00
void CPlayerGun::TouchModel(const CStateManager& mgr)
2017-02-18 02:19:50 +00:00
{
2017-08-25 06:18:09 +00:00
if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
{
x73c_gunMotion->GetModelData().Touch(mgr, 0);
switch (x33c_gunOverrideMode)
{
case EGunOverrideMode::One:
if (x75c_phazonBeam)
x75c_phazonBeam->Touch(mgr);
break;
case EGunOverrideMode::Two:
if (x738_nextBeam)
x738_nextBeam->Touch(mgr);
break;
default:
if (!x833_28_phazonBeamActive)
x72c_currentBeam->Touch(mgr);
else
x75c_phazonBeam->Touch(mgr);
break;
}
x72c_currentBeam->TouchHolo(mgr);
x740_grappleArm->TouchModel(mgr);
x6e0_rightHandModel.Touch(mgr, 0);
}
2017-02-18 02:19:50 +00:00
2017-08-25 06:18:09 +00:00
if (x734_)
{
x734_->Touch(mgr);
x734_->TouchHolo(mgr);
}
2017-02-18 02:19:50 +00:00
}
void CPlayerGun::DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr)
{
x398_damageAmt = damage;
x3dc_damageLocation = location;
}
2017-08-26 04:36:25 +00:00
void CPlayerGun::StopChargeSound(CStateManager& mgr)
{
if (x2e0_chargeSfx)
{
CSfxManager::SfxStop(x2e0_chargeSfx);
x2e0_chargeSfx.reset();
}
if (x830_chargeRumbleHandle != -1)
{
mgr.GetRumbleManager().StopRumble(x830_chargeRumbleHandle);
x830_chargeRumbleHandle = -1;
}
}
2017-08-25 06:18:09 +00:00
void CPlayerGun::ResetCharge(CStateManager& mgr, bool b1)
{
2017-08-26 04:36:25 +00:00
if (x32c_)
StopChargeSound(mgr);
if ((x2f8_ & 0x8) != 0x8 && (x2f8_ & 0x10) != 0x10)
{
bool r30 = !(mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed && !b1);
if (x832_27_ || r30)
PlayAnim(NWeaponTypes::EGunAnimType::Zero, false);
if (r30)
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero);
if ((x2f8_ & 0x2) != 0x2 || x330_chargeWeaponIdx != 0)
{
if ((x2f8_ & 0x8) != 0x8)
{
x2f8_ |= 0x1;
x2f8_ &= 0xFFE9;
}
x318_ = 0;
x31c_missileMode = EMissleMode::Inactive;
}
}
x32c_ = 0;
x330_chargeWeaponIdx = 0;
x320_ = x310_selectedBeam;
x833_30_ = true;
x832_27_ = false;
x832_26_ = false;
x344_ = 0.f;
}
2017-08-25 06:18:09 +00:00
2017-08-26 04:36:25 +00:00
bool CPlayerGun::ExitMissile()
{
if ((x2f8_ & 0x1) == 0x1)
return true;
if ((x2f8_ & 0x10) == 0x10 || x338_ == 2)
return false;
x338_ = 2;
PlayAnim(NWeaponTypes::EGunAnimType::FromMissile, false);
return false;
2017-08-25 06:18:09 +00:00
}
2017-08-26 04:36:25 +00:00
static const CPlayerState::EItemType skBeamArr[] =
{
CPlayerState::EItemType::PowerBeam,
CPlayerState::EItemType::IceBeam,
CPlayerState::EItemType::WaveBeam,
CPlayerState::EItemType::PlasmaBeam
};
static const ControlMapper::ECommands mBeamCtrlCmd[] =
{
ControlMapper::ECommands::PowerBeam,
ControlMapper::ECommands::IceBeam,
ControlMapper::ECommands::WaveBeam,
ControlMapper::ECommands::PlasmaBeam,
};
2017-08-25 06:18:09 +00:00
void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr)
2017-07-16 06:13:37 +00:00
{
2017-08-26 04:36:25 +00:00
CPlayerState& playerState = *mgr.GetPlayerState();
float maxBeamInput = 0.f;
int selectBeam = -1;
for (int i=0 ; i<4 ; ++i)
{
if (playerState.HasPowerUp(skBeamArr[i]))
{
float inputVal = ControlMapper::GetAnalogInput(mBeamCtrlCmd[i], input);
if (inputVal > 0.65f && inputVal > maxBeamInput)
{
maxBeamInput = inputVal;
selectBeam = i;
}
}
}
if (selectBeam < 0)
return;
2017-07-16 06:13:37 +00:00
2017-08-26 04:36:25 +00:00
x833_25_ = true;
if (x310_selectedBeam != selectBeam && playerState.HasPowerUp(skBeamArr[selectBeam]))
{
x314_pendingSelectedBeam = u32(selectBeam);
u32 flags = 0;
if ((x2f8_ & 0x10) == 0x10)
flags = 0x10;
flags |= 0x8;
x2f8_ = flags;
PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false);
if (x833_31_ || x744_auxWeapon->IsComboFxActive(mgr) || x832_26_)
{
x832_30_ = true;
x740_grappleArm->EnterIdle(mgr);
}
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero);
x338_ = 5;
x2e4_invalidSfx.reset();
}
else if (playerState.HasPowerUp(skBeamArr[selectBeam]))
{
if (ExitMissile())
{
if (!CSfxManager::IsPlaying(x2e4_invalidSfx))
x2e4_invalidSfx = PlaySfx(1763, x834_27_underwater, false, 0.165f);
}
else
{
x2e4_invalidSfx.reset();
}
}
2017-07-16 06:13:37 +00:00
}
2017-08-25 06:18:09 +00:00
void CPlayerGun::SetPhazonBeamMorph(bool intoPhazonBeam)
{
x39c_ = intoPhazonBeam ? 0.f : 1.f;
x835_27_intoPhazonBeam = intoPhazonBeam;
x835_26_phazonBeamMorphing = true;
}
void CPlayerGun::Reset(CStateManager& mgr, bool b1)
{
x72c_currentBeam->Reset(mgr);
x832_25_ = false;
x832_24_ = false;
x833_26_ = false;
x348_ = 0.f;
SetGunLightActive(false, mgr);
if ((x2f8_ & 0x10) != 0x10)
{
if (!b1 && (x2f8_ & 0x2) != 0x2)
{
if ((x2f8_ & 0x8) != 0x8)
{
x2f8_ |= 0x1;
x2f8_ &= 0xFFE9;
}
x318_ = 0;
x31c_missileMode = EMissleMode::Inactive;
}
}
else
{
x2f8_ &= ~0x7;
}
}
void CPlayerGun::ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState, bool playSelectionSfx)
{
StopContinuousBeam(mgr, true);
if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam))
ResetCharge(mgr, false);
CAnimPlaybackParms parms(skBeamAnimIds[x314_pendingSelectedBeam], -1, 1.f, true);
x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false);
Reset(mgr, false);
if (playSelectionSfx)
CSfxManager::SfxStart(1774, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId);
x2ec_firing &= ~0x1;
x320_ = x310_selectedBeam;
x833_30_ = true;
}
2017-08-26 04:36:25 +00:00
CSfxHandle CPlayerGun::PlaySfx(u16 sfx, bool underwater, bool looped, float pan)
2017-08-25 06:18:09 +00:00
{
CSfxHandle hnd = CSfxManager::SfxStart(sfx, 1.f, pan, true, 0x7f, looped, kInvalidAreaId);
CSfxManager::SfxSpan(hnd, 0.f);
if (underwater)
CSfxManager::PitchBend(hnd, -1.f);
2017-08-26 04:36:25 +00:00
return hnd;
2017-08-25 06:18:09 +00:00
}
static const u16 skFromMissileSound[] = { 1824, 1849, 1851, 1853 };
static const u16 skFromBeamSound[] = { 0, 1822, 1828, 1826 };
static const u16 skToMissileSound[] = { 1823, 1829, 1850, 1852 };
2017-08-26 04:36:25 +00:00
void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop)
2017-08-25 06:18:09 +00:00
{
if (x338_ != 5)
2017-08-26 04:36:25 +00:00
x72c_currentBeam->PlayAnim(type, loop);
2017-08-25 06:18:09 +00:00
u16 sfx = 0xffff;
switch (type)
{
case NWeaponTypes::EGunAnimType::FromMissile:
x2f8_ &= ~0x4;
sfx = skFromMissileSound[x310_selectedBeam];
break;
case NWeaponTypes::EGunAnimType::MissileReload:
sfx = 1769;
break;
case NWeaponTypes::EGunAnimType::FromBeam:
sfx = skFromBeamSound[x310_selectedBeam];
break;
case NWeaponTypes::EGunAnimType::ToMissile:
x2f8_ &= ~0x1;
sfx = skToMissileSound[x310_selectedBeam];
break;
default:
break;
}
if (sfx != 0xffff)
PlaySfx(sfx, x834_27_underwater, false, 0.165f);
}
void CPlayerGun::CancelCharge(CStateManager& mgr, bool withEffect)
{
if (withEffect)
{
x32c_ = 9;
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Three);
}
else
{
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero);
}
x834_24_charging = false;
x348_ = 0.f;
x72c_currentBeam->ActivateCharge(false, false);
SetGunLightActive(false, mgr);
}
void CPlayerGun::HandlePhazonBeamChange(CStateManager& mgr)
{
bool inMorph = false;
switch (x33c_gunOverrideMode)
{
case EGunOverrideMode::Normal:
SetPhazonBeamMorph(true);
x338_ = 8;
inMorph = true;
break;
case EGunOverrideMode::Three:
if (!x835_25_inPhazonBeam)
{
SetPhazonBeamMorph(true);
x338_ = 9;
inMorph = true;
if (x75c_phazonBeam)
{
x75c_phazonBeam->SetX274_25(false);
x75c_phazonBeam->SetX274_26(true);
}
}
break;
default:
break;
}
if (inMorph)
{
ResetBeamParams(mgr, *mgr.GetPlayerState(), true);
x2f8_ = 0x8;
PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false);
if (x833_31_)
{
x832_30_ = true;
x740_grappleArm->EnterIdle(mgr);
}
CancelCharge(mgr, false);
}
}
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 (!x835_25_inPhazonBeam)
HandleBeamChange(input, mgr);
else
HandlePhazonBeamChange(mgr);
}
}
void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr)
{
CPlayerState& state = *mgr.GetPlayerState();
2017-08-26 04:36:25 +00:00
bool damageNotMorphed = (x834_30_inBigStrike &&
2017-08-25 06:18:09 +00:00
mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed);
if (x832_24_ || damageNotMorphed || (x2f8_ & 0x8) == 0x8)
return;
if (state.HasPowerUp(CPlayerState::EItemType::ChargeBeam))
{
if (!state.ItemEnabled(CPlayerState::EItemType::ChargeBeam))
state.EnableItem(CPlayerState::EItemType::ChargeBeam);
}
else if (state.ItemEnabled(CPlayerState::EItemType::ChargeBeam))
{
state.DisableItem(CPlayerState::EItemType::ChargeBeam);
ResetCharge(mgr, false);
}
switch (mgr.GetPlayer().GetMorphballTransitionState())
{
default:
x2f4_ = 0;
break;
case CPlayer::EPlayerMorphBallState::Unmorphed:
if ((x2f8_ & 0x10) != 0x10)
HandleWeaponChange(input, mgr);
case CPlayer::EPlayerMorphBallState::Morphed:
x2f4_ = ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) ? 1 : 0;
x2f4_ |= ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) ? 2 : 0;
break;
}
}
2017-08-26 04:36:25 +00:00
void CPlayerGun::UnLoadFidget()
2017-07-17 03:04:14 +00:00
{
2017-08-26 04:36:25 +00:00
if ((x2fc_ & 0x1) == 0x1)
x73c_gunMotion->GunController().UnLoadFidget();
if ((x2fc_ & 0x2) == 0x2)
x72c_currentBeam->UnLoadFidget();
if ((x2fc_ & 0x4) == 0x4)
if (CGunController* gc = x740_grappleArm->GunController())
gc->UnLoadFidget();
x2fc_ = 0;
}
2017-07-17 03:04:14 +00:00
2017-08-26 04:36:25 +00:00
void CPlayerGun::ReturnArmAndGunToDefault(CStateManager& mgr, bool b1)
{
if (b1 || !x833_31_)
{
x73c_gunMotion->ReturnToDefault(mgr, false);
x740_grappleArm->ReturnToDefault(mgr, 0.f, false);
}
if (!x834_25_)
x72c_currentBeam->ReturnToDefault(mgr);
x834_25_ = false;
2017-07-17 03:04:14 +00:00
}
2017-08-26 04:36:25 +00:00
void CPlayerGun::ReturnToRestPose()
{
if (x832_31_)
return;
if ((x2f8_ & 0x1) == 0x1)
PlayAnim(NWeaponTypes::EGunAnimType::Zero, false);
else if ((x2f8_ & 0x4) == 0x4)
PlayAnim(NWeaponTypes::EGunAnimType::ToMissile, false);
x832_31_ = true;
}
void CPlayerGun::ResetIdle(CStateManager& mgr)
2017-07-17 03:04:14 +00:00
{
2017-08-26 04:36:25 +00:00
x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::GunFireNoBob, mgr);
if (x3a4_fidget.GetState() != CFidget::EState::Zero)
{
if (x3a4_fidget.GetState() == CFidget::EState::Seven)
UnLoadFidget();
ReturnArmAndGunToDefault(mgr, true);
}
x3a4_fidget.ResetAll();
ReturnToRestPose();
if (x324_ != 0)
x324_ = 0;
if (!x740_grappleArm->GetActive())
x834_26_ = false;
}
2017-07-17 03:04:14 +00:00
2017-08-26 04:36:25 +00:00
void CPlayerGun::CancelFiring(CStateManager& mgr)
{
if (x32c_ == 8)
ReturnArmAndGunToDefault(mgr, true);
if ((x2f8_ & 0x10) == 0x10)
{
StopContinuousBeam(mgr, true);
if ((x2f8_ & 0x8) == 0x8)
{
x2f8_ |= 0x1;
x2f8_ &= 0xFFE9;
}
x318_ = 0;
x31c_missileMode = EMissleMode::Inactive;
}
if (x32c_ != 0)
{
x72c_currentBeam->ActivateCharge(false, false);
SetGunLightActive(false, mgr);
ResetCharge(mgr, true);
}
Reset(mgr, (x2f8_ & 0x2) == 0x2);
2017-07-17 03:04:14 +00:00
}
2017-07-23 23:45:04 +00:00
float CPlayerGun::GetBeamVelocity() const
{
if (x72c_currentBeam->IsLoaded())
return x72c_currentBeam->GetVelocityInfo().GetVelocity(x330_chargeWeaponIdx).y;
return 10.f;
}
2017-08-25 06:18:09 +00:00
void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1)
2017-08-26 04:36:25 +00:00
{
if ((x2f8_ & 0x10) == 0x10)
{
ReturnArmAndGunToDefault(mgr, false);
x744_auxWeapon->StopComboFx(mgr, b1);
switch (x310_selectedBeam)
{
case 0:
case 2:
case 3:
// All except ice
if (x310_selectedBeam != 0 || x833_28_phazonBeamActive)
{
x72c_currentBeam->EnableSecondaryFx(
b1 ? CGunWeapon::ESecondaryFxType::Zero : CGunWeapon::ESecondaryFxType::Three);
}
break;
default:
break;
}
}
else if (x833_28_phazonBeamActive)
{
if (static_cast<CPhazonBeam*>(x72c_currentBeam)->IsFiring())
static_cast<CPhazonBeam*>(x72c_currentBeam)->StopBeam(mgr, b1);
}
else if (x310_selectedBeam == 3) // Plasma
{
if (static_cast<CPlasmaBeam*>(x72c_currentBeam)->IsFiring())
static_cast<CPlasmaBeam*>(x72c_currentBeam)->StopBeam(mgr, b1);
}
}
void CPlayerGun::CMotionState::Update(bool b1, float dt, zeus::CTransform& xf, CStateManager& mgr)
{
}
void CPlayerGun::ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr)
{
}
void CPlayerGun::GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mData, const std::string& lctrName,
bool b1, bool b2)
{
}
void CPlayerGun::UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr)
{
}
void CPlayerGun::ProcessGunMorph(float dt, CStateManager& mgr)
{
}
void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr)
{
}
void CPlayerGun::UpdateChargeState(float dt, CStateManager& mgr)
{
}
void CPlayerGun::UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr)
{
}
void CPlayerGun::DoUserAnimEvents(float dt, CStateManager& mgr)
{
}
TUniqueId CPlayerGun::GetTargetId(CStateManager& mgr) const
{
return {};
}
void CPlayerGun::CancelLockOn()
{
}
void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CStateManager& mgr)
{
}
void CPlayerGun::UpdateGunIdle(bool b1, float camBobT, float dt, CStateManager& mgr)
2017-08-25 06:18:09 +00:00
{
}
2017-08-26 04:36:25 +00:00
static const float chargeShakeTbl[] = { -0.001f, 0.f, 0.001f };
static const CMaterialFilter sAimFilter =
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough});
2017-08-16 05:34:02 +00:00
void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateManager& mgr)
{
2017-08-26 04:36:25 +00:00
CPlayer& player = mgr.GetPlayer();
CPlayerState& playerState = *mgr.GetPlayerState();
bool isUnmorphed = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed;
bool becameFrozen;
if (isUnmorphed)
becameFrozen = !x834_29_frozen && player.GetFrozenState();
else
becameFrozen = false;
bool becameThawed;
if (isUnmorphed)
becameThawed = x834_29_frozen && !player.GetFrozenState();
else
becameThawed = false;
x834_29_frozen = isUnmorphed && player.GetFrozenState();
float advDt;
if (x834_29_frozen)
advDt = 0.f;
else
advDt = dt;
bool r23 = x678_morph.GetGunState() != CGunMorph::EGunState::One;
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay || r23)
x6e0_rightHandModel.AdvanceAnimation(advDt, mgr, kInvalidAreaId, true);
if (r23 && x734_ != 0 && x734_ != x72c_currentBeam)
{
x744_auxWeapon->LoadIdle();
x734_->Update(advDt, mgr);
}
if (!x744_auxWeapon->IsLoaded())
x744_auxWeapon->LoadIdle();
if (becameFrozen)
{
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero);
x72c_currentBeam->BuildSecondaryEffect(CGunWeapon::ESecondaryFxType::One);
}
else if (becameThawed)
{
x72c_currentBeam->BuildSecondaryEffect(CGunWeapon::ESecondaryFxType::Two);
}
if (becameFrozen || becameThawed)
{
x2f4_ = 0;
x2ec_firing = 0;
CancelFiring(mgr);
}
x72c_currentBeam->Update(advDt, mgr);
x73c_gunMotion->Update(advDt * x370_gunMotionSpeedMult, mgr);
x740_grappleArm->Update(grappleSwingT, advDt, mgr);
if (x338_ != 0)
{
if (x678_morph.GetGunState() == CGunMorph::EGunState::Zero)
{
if (x338_ == 5)
{
ChangeWeapon(playerState, mgr);
x338_ = 0;
}
}
else if (!x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body") ||
x832_30_)
{
bool r24 = true;
switch (x338_)
{
case 1:
x2f8_ &= 0x1;
x2f8_ |= 0x6;
x318_ = 1;
x31c_missileMode = EMissleMode::Active;
break;
case 2:
if ((x2f8_ & 0x8) != 0x8)
{
x2f8_ |= 0x1;
x2f8_ &= 0xFFE9;
}
x318_ = 0;
x31c_missileMode = EMissleMode::Inactive;
x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown;
break;
case 4:
PlayAnim(NWeaponTypes::EGunAnimType::MissileReload, false);
x338_ = 3;
r24 = false;
break;
case 3:
x2f8_ |= 0x4;
break;
case 5:
ChangeWeapon(playerState, mgr);
break;
case 6:
x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown;
x2f8_ &= ~0x8;
if ((x2f8_ & 0x8) != 0x8)
{
x2f8_ |= 0x1;
x2f8_ &= 0xFFE9;
}
x318_ = 0;
x31c_missileMode = EMissleMode::Inactive;
break;
case 8:
if (x75c_phazonBeam->IsLoaded())
break;
x72c_currentBeam->SetLeavingBeam();
x75c_phazonBeam->Load(mgr, false);
x33c_gunOverrideMode = EGunOverrideMode::One;
break;
case 9:
if (x738_nextBeam->IsLoaded())
break;
x72c_currentBeam->SetLeavingBeam();
x738_nextBeam->Load(mgr, false);
x33c_gunOverrideMode = EGunOverrideMode::Two;
break;
default:
break;
}
if (r24)
x338_ = 0;
}
}
if (x37c_ < 0.2f)
{
x37c_ += advDt;
}
else
{
x37c_ = 0.f;
if (x30c_ > 0)
x30c_ -= 1;
}
if (x32c_ != 0 && !player.GetFrozenState())
{
x34c_shakeX = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor;
x350_shakeZ = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor;
}
if (!x72c_currentBeam->IsLoaded())
return;
GetLctrWithShake(x4d8_gunLocalXf, x73c_gunMotion->GetModelData(), "GBSE_SDK", true, true);
GetLctrWithShake(x418_beamLocalXf, x72c_currentBeam->GetSolidModelData(), "LBEAM", false, true);
GetLctrWithShake(x508_elbowLocalXf, x72c_currentBeam->GetSolidModelData(), "elbow", false, false);
x4a8_gunWorldXf = x3e8_xf * x4d8_gunLocalXf * x550_camBob.GetCameraBobTransformation();
if (x740_grappleArm->GetActive() && !x740_grappleArm->IsGrappling())
UpdateLeftArmTransform(x72c_currentBeam->GetSolidModelData(), mgr);
x6a0_motionState.Update(x2f0_ != 0 && x832_28_ && x32c_ < 2 && !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);
zeus::CTransform beamWorldXf = x4a8_gunWorldXf * x418_beamLocalXf;
if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed &&
!mgr.GetCameraManager()->IsInCinematicCamera())
{
rstl::reserved_vector<TUniqueId, 1024> nearList;
zeus::CAABox aabb = x72c_currentBeam->GetBounds().getTransformedAABox(x4a8_gunWorldXf);
mgr.BuildNearList(nearList, aabb, sAimFilter, &player);
TUniqueId bestId = kInvalidUniqueId;
zeus::CVector3f dir = x4a8_gunWorldXf.basis[1].normalized();
zeus::CVector3f pos = dir * -0.5f + x4a8_gunWorldXf.origin;
CRayCastResult result = mgr.RayWorldIntersection(bestId, pos, dir, 3.5f, sAimFilter, nearList);
x833_29_pointBlankWorldSurface = result.IsValid();
if (result.IsValid())
{
x448_elbowWorldXf = x4a8_gunWorldXf * x508_elbowLocalXf;
x448_elbowWorldXf.origin += dir * -0.5f;
beamWorldXf.origin = result.GetPoint();
}
}
else
{
x833_29_pointBlankWorldSurface = false;
}
2017-08-16 05:34:02 +00:00
2017-08-26 04:36:25 +00:00
zeus::CTransform beamTargetXf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : beamWorldXf;
zeus::CVector3f camTrans = mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr);
beamWorldXf.origin += camTrans;
beamTargetXf.origin += camTrans;
if (x832_25_)
{
bool emitting = x833_30_ ? x344_ < 1.f : false;
zeus::CVector3f scale((emitting && x832_26_) ? (1.f - x344_) * 2.f : 2.f);
x72c_currentBeam->UpdateMuzzleFx(advDt, scale, x418_beamLocalXf.origin, emitting);
CElementGen& gen = *x800_auxMuzzleGenerators[x320_];
gen.SetGlobalOrientAndTrans(x418_beamLocalXf);
gen.SetGlobalScale(scale);
gen.SetParticleEmission(emitting);
gen.Update(advDt);
}
if (x748_rainSplashGenerator)
x748_rainSplashGenerator->Update(advDt, mgr);
UpdateGunLight(beamWorldXf, mgr);
ProcessGunMorph(advDt, mgr);
if (x835_26_phazonBeamMorphing)
ProcessPhazonGunMorph(advDt, mgr);
if (x832_26_ && x77c_)
{
x77c_->SetGlobalTranslation(x418_beamLocalXf.origin);
x77c_->SetGlobalOrientation(x418_beamLocalXf.getRotation());
x77c_->Update(advDt);
x344_ += advDt * 4.f;
}
if (x35c_bombTime > 0.f)
{
x35c_bombTime -= advDt;
if (x35c_bombTime <= 0.f)
x308_bombCount = 3;
}
if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam) && x32c_ != 0)
{
UpdateChargeState(advDt, mgr);
}
else
{
x340_chargeBeamFactor -= advDt;
if (x340_chargeBeamFactor < 0.f)
x340_chargeBeamFactor = 0.f;
}
UpdateAuxWeapons(advDt, beamTargetXf, mgr);
DoUserAnimEvents(advDt, mgr);
if (x304_ == 1 && GetTargetId(mgr) != kInvalidUniqueId)
{
if (!x832_29_ && !x832_26_ && (x2f8_ & 0x10) != 0x10)
{
x832_29_ = true;
x6a0_motionState.SetState(CMotionState::EMotionState::Two);
ReturnArmAndGunToDefault(mgr, true);
}
}
else
{
CancelLockOn();
}
UpdateWeaponFire(advDt, playerState, mgr);
UpdateGunIdle(x364_ > 0.f, cameraBobT, advDt, mgr);
if ((x2ec_firing & 0x1) == 0x1)
{
x378_ = 0.f;
}
else if (x378_ < 2.f)
{
x378_ += advDt;
if (x378_ > 1.f)
{
x30c_ = 0;
x380_ = 0.f;
}
}
if (x38c_ > 0.f)
x38c_ -= advDt;
if (x30c_ > 5 && x380_ < 2.f)
x380_ += advDt;
if (x384_ > 0.f)
x384_ -= advDt;
if (x364_ > 0.f)
{
x2f4_ = 0;
x364_ -= advDt;
}
if (isUnmorphed && (x2f8_ & 0x4) == 0x4)
{
x3a0_ -= advDt;
if (x3a0_ < 0.f)
{
x3a0_ = 0.f;
ExitMissile();
}
}
2017-08-16 05:34:02 +00:00
}
2017-07-31 05:19:05 +00:00
void CPlayerGun::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos)
{
}
void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const
{
}
void CPlayerGun::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const
{
}
2017-08-16 05:34:02 +00:00
TUniqueId CPlayerGun::DropPowerBomb(CStateManager& mgr)
{
return {};
}
}