2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-13 17:51:21 +00:00
metaforce/Runtime/Weapon/CAuxWeapon.cpp
Lioncash 450bcd019e CAuxWeapon: Replace always false condition with false in Fire()
Given we already check if chargeState is Normal previously, there's no
way that this can also be Charged at the same time.
2020-02-25 04:36:10 -05:00

324 lines
12 KiB
C++

#include "Runtime/Weapon/CAuxWeapon.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Weapon/CEnergyProjectile.hpp"
#include "Runtime/Weapon/CNewFlameThrower.hpp"
#include "Runtime/Weapon/CWaveBuster.hpp"
namespace urde {
static const CCameraShakeData skHardShake = {
0.3f, 100.f, 0, zeus::skZero3f, {}, {1, {0, 0.f, 0.f, 0.3f, -2.f}, {1, 0.f, 0.f, 0.05f, 0.5f}}, {}};
CAuxWeapon::CAuxWeapon(TUniqueId playerId)
: x0_missile(g_SimplePool->GetObj("Missile"))
, xc_flameMuzzle(g_SimplePool->GetObj("FlameMuzzle"))
, x18_busterMuzzle(g_SimplePool->GetObj("BusterMuzzle"))
, x6c_playerId(playerId) {
x0_missile.GetObj();
xc_flameMuzzle.GetObj();
x18_busterMuzzle.GetObj();
x80_24_isLoaded = false;
InitComboData();
}
static const char* skComboNames[] = {"SuperMissile", "IceCombo", "WaveBuster", "FlameThrower", "SuperMissile"};
void CAuxWeapon::InitComboData() {
for (int i = 0; i < 5; ++i)
x28_combos.push_back(g_SimplePool->GetObj(skComboNames[i]));
}
void CAuxWeapon::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
if (msg == EScriptObjectMessage::Deleted) {
DeleteFlameThrower(mgr);
DeleteWaveBusterBeam(mgr);
}
}
bool CAuxWeapon::IsComboFxActive(const CStateManager& mgr) const {
switch (x74_firingBeamId) {
case CPlayerState::EBeamId::Wave:
if (const CEntity* ent = mgr.GetObjectById(x70_waveBusterId))
return static_cast<const CWaveBuster*>(ent)->IsFiring();
break;
case CPlayerState::EBeamId::Plasma:
if (const CEntity* ent = mgr.GetObjectById(x6e_flameThrowerId))
return static_cast<const CNewFlameThrower*>(ent)->IsFiring();
break;
default:
break;
}
return false;
}
void CAuxWeapon::Load(CPlayerState::EBeamId curBeam, CStateManager& mgr) {
x80_24_isLoaded = false;
switch (x78_loadBeamId) {
case CPlayerState::EBeamId::Wave:
DeleteWaveBusterBeam(mgr);
break;
case CPlayerState::EBeamId::Plasma:
DeleteFlameThrower(mgr);
break;
default:
break;
}
x28_combos[int(x78_loadBeamId)].Unlock();
x28_combos[int(curBeam)].Lock();
x78_loadBeamId = curBeam;
LoadIdle();
}
void CAuxWeapon::StopComboFx(CStateManager& mgr, bool deactivate) {
switch (x74_firingBeamId) {
case CPlayerState::EBeamId::Wave: {
auto* wb = static_cast<CWaveBuster*>(mgr.ObjectById(x70_waveBusterId));
if (wb) {
wb->ResetBeam(deactivate);
DeleteWaveBusterBeam(mgr);
}
break;
}
case CPlayerState::EBeamId::Plasma: {
auto* ft = static_cast<CNewFlameThrower*>(mgr.ObjectById(x6e_flameThrowerId));
if (ft) {
mgr.GetPlayerState()->SetFiringComboBeam(false);
if (ft->IsFiring()) {
ft->Reset(mgr, deactivate);
FreeComboVoiceId();
} else if (ft->GetActive() && deactivate) {
ft->Reset(mgr, deactivate);
}
}
break;
}
default:
break;
}
if (deactivate) {
x74_firingBeamId = CPlayerState::EBeamId::Invalid;
x68_ammoConsumeTimer = 0.f;
}
}
bool CAuxWeapon::UpdateComboFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos,
const zeus::CTransform& xf, CStateManager& mgr) {
if (!x80_24_isLoaded || x74_firingBeamId == CPlayerState::EBeamId::Invalid)
return false;
bool firing = false;
if (x7c_comboSfx && !CSfxManager::IsPlaying(x7c_comboSfx))
FreeComboVoiceId();
switch (x74_firingBeamId) {
case CPlayerState::EBeamId::Wave:
case CPlayerState::EBeamId::Plasma: {
bool firingFx = false;
if (x74_firingBeamId == CPlayerState::EBeamId::Wave) {
auto* wb = static_cast<CWaveBuster*>(mgr.ObjectById(x70_waveBusterId));
if (wb && wb->IsFiring()) {
wb->UpdateFx(xf, dt, mgr);
firing = true;
firingFx = true;
} else {
DeleteWaveBusterBeam(mgr);
mgr.GetPlayerState()->SetFiringComboBeam(false);
}
} else {
auto* ft = static_cast<CNewFlameThrower*>(mgr.ObjectById(x6e_flameThrowerId));
bool needsDelete = true;
if (ft) {
firingFx = ft->CanRenderAuxEffects();
if (ft->GetActive()) {
ft->UpdateFx(xf, dt, mgr);
firing = ft->IsFiring();
}
if (x6e_flameThrowerId != kInvalidUniqueId)
needsDelete = ft->AreEffectsFinished();
}
if (needsDelete) {
DeleteFlameThrower(mgr);
mgr.GetPlayerState()->SetFiringComboBeam(false);
}
}
if (firingFx) {
x68_ammoConsumeTimer += dt;
if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles) > 0) {
if (x68_ammoConsumeTimer >= mgr.GetPlayerState()->GetComboFireAmmoPeriod()) {
mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::Missiles, 1);
x68_ammoConsumeTimer = 0.f;
}
}
}
if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles) == 0)
StopComboFx(mgr, false);
x24_muzzleFxGen->SetGlobalTranslation(pos);
x24_muzzleFxGen->SetGlobalScale(scale);
x24_muzzleFxGen->SetParticleEmission(firingFx);
x24_muzzleFxGen->Update(dt);
break;
}
default:
break;
}
return firing;
}
void CAuxWeapon::FreeComboVoiceId() {
CSfxManager::SfxStop(x7c_comboSfx);
x7c_comboSfx.reset();
}
void CAuxWeapon::DeleteFlameThrower(CStateManager& mgr) {
FreeComboVoiceId();
if (x6e_flameThrowerId != kInvalidUniqueId) {
mgr.FreeScriptObject(x6e_flameThrowerId);
x6e_flameThrowerId = kInvalidUniqueId;
x74_firingBeamId = CPlayerState::EBeamId::Invalid;
mgr.GetPlayerState()->SetFiringComboBeam(false);
}
}
void CAuxWeapon::CreateFlameThrower(const zeus::CTransform& xf, CStateManager& mgr, float dt) {
DeleteFlameThrower(mgr);
if (x6e_flameThrowerId != kInvalidUniqueId)
return;
CAssetId resInfo[] = {NWeaponTypes::get_asset_id_from_name("NFTMainFire"),
NWeaponTypes::get_asset_id_from_name("NFTMainSmoke"),
NWeaponTypes::get_asset_id_from_name("NFTSwooshCenter"),
NWeaponTypes::get_asset_id_from_name("NFTSwooshFire"),
NWeaponTypes::get_asset_id_from_name("NFTSecondarySmoke"),
NWeaponTypes::get_asset_id_from_name("NFTSecondaryFire"),
NWeaponTypes::get_asset_id_from_name("NFTSecondarySparks"),
{}};
x6e_flameThrowerId = mgr.AllocateUniqueId();
CNewFlameThrower* ft = new CNewFlameThrower(
x28_combos[3], "Player_FlameThrower", EWeaponType::Plasma, resInfo, xf, EMaterialTypes::Player,
CGunWeapon::GetShotDamageInfo(g_tweakPlayerGun->GetComboShotInfo(3), mgr), x6e_flameThrowerId, kInvalidAreaId,
x6c_playerId, EProjectileAttrib::None);
mgr.AddObject(ft);
ft->Think(dt, mgr);
ft->StartFiring(xf, mgr);
x24_muzzleFxGen = std::make_unique<CElementGen>(xc_flameMuzzle);
x7c_comboSfx = NWeaponTypes::play_sfx(SFXwpn_combo_flamethrower, false, true, 0.165f);
mgr.GetCameraManager()->AddCameraShaker(skHardShake, false);
mgr.GetPlayerState()->SetFiringComboBeam(true);
x74_firingBeamId = CPlayerState::EBeamId::Plasma;
}
void CAuxWeapon::DeleteWaveBusterBeam(CStateManager& mgr) {
FreeComboVoiceId();
if (x70_waveBusterId != kInvalidUniqueId) {
mgr.FreeScriptObject(x70_waveBusterId);
x70_waveBusterId = kInvalidUniqueId;
x74_firingBeamId = CPlayerState::EBeamId::Invalid;
mgr.GetPlayerState()->SetFiringComboBeam(false);
}
}
void CAuxWeapon::CreateWaveBusterBeam(EProjectileAttrib attribs, TUniqueId homingTarget, const zeus::CTransform& xf,
CStateManager& mgr) {
DeleteFlameThrower(mgr);
if (x70_waveBusterId != kInvalidUniqueId)
return;
x70_waveBusterId = mgr.AllocateUniqueId();
CWaveBuster* wb = new CWaveBuster(x28_combos[2], EWeaponType::Wave, xf, EMaterialTypes::Player,
CGunWeapon::GetShotDamageInfo(g_tweakPlayerGun->GetComboShotInfo(2), mgr),
x70_waveBusterId, kInvalidAreaId, x6c_playerId, homingTarget, attribs);
mgr.AddObject(wb);
x24_muzzleFxGen = std::make_unique<CElementGen>(x18_busterMuzzle);
x7c_comboSfx = NWeaponTypes::play_sfx(SFXwpn_combo_wavebuster, false, true, 0.165f);
mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedShotCameraShakeData, false);
mgr.GetPlayerState()->SetFiringComboBeam(true);
x74_firingBeamId = CPlayerState::EBeamId::Wave;
}
static const u16 skSoundId[] = {1810, 1837, 1847, 1842, 1810};
void CAuxWeapon::LaunchMissile(float dt, bool underwater, bool charged, CPlayerState::EBeamId currentBeam,
EProjectileAttrib attrib, const zeus::CTransform& xf, TUniqueId homingId,
CStateManager& mgr) {
const SShotParam& info =
charged ? g_tweakPlayerGun->GetComboShotInfo(int(currentBeam)) : g_tweakPlayerGun->GetMissileInfo();
u16 sfxId = charged ? skSoundId[int(currentBeam)] : u16(SFXwpn_fire_missile);
CEnergyProjectile* proj = new CEnergyProjectile(
true, charged ? x28_combos[int(currentBeam)] : x0_missile, charged ? EWeaponType::Power : EWeaponType::Missile,
xf, EMaterialTypes::Player, CGunWeapon::GetShotDamageInfo(info, mgr), mgr.AllocateUniqueId(), kInvalidAreaId,
x6c_playerId, homingId, attrib | EProjectileAttrib::ArmCannon, underwater, zeus::skOne3f, {}, -1, false);
mgr.AddObject(proj);
proj->Think(dt, mgr);
if (charged) {
proj->SetCameraShake(CCameraShakeData::BuildMissileCameraShake(0.25f, 0.75f, 50.f, proj->GetTranslation()));
mgr.GetCameraManager()->AddCameraShaker(skHardShake, false);
} else {
mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerMissileFire, 0.5f, ERumblePriority::One);
}
x7c_comboSfx = NWeaponTypes::play_sfx(sfxId, underwater, false, 0.165f);
}
void CAuxWeapon::Fire(float dt, bool underwater, CPlayerState::EBeamId currentBeam, EChargeState chargeState,
const zeus::CTransform& xf, CStateManager& mgr, EWeaponType type, TUniqueId homingId) {
if (!x80_24_isLoaded)
return;
EProjectileAttrib attrib = EProjectileAttrib::None;
if (chargeState == EChargeState::Charged)
attrib = CGameProjectile::GetBeamAttribType(type) | EProjectileAttrib::ComboShot;
if (chargeState == EChargeState::Normal) {
LaunchMissile(dt, underwater, false, currentBeam, attrib, xf, homingId, mgr);
} else {
switch (currentBeam) {
case CPlayerState::EBeamId::Power:
case CPlayerState::EBeamId::Ice:
LaunchMissile(dt, underwater, chargeState == EChargeState::Charged, currentBeam, attrib, xf, homingId, mgr);
break;
case CPlayerState::EBeamId::Wave:
CreateWaveBusterBeam(attrib, homingId, xf, mgr);
break;
case CPlayerState::EBeamId::Plasma:
CreateFlameThrower(xf, mgr, dt);
break;
default:
break;
}
}
}
void CAuxWeapon::LoadIdle() { x80_24_isLoaded = x28_combos[int(x78_loadBeamId)].IsLoaded(); }
void CAuxWeapon::RenderMuzzleFx() const {
switch (x74_firingBeamId) {
case CPlayerState::EBeamId::Wave:
case CPlayerState::EBeamId::Plasma:
x24_muzzleFxGen->Render();
break;
default:
break;
}
}
TUniqueId CAuxWeapon::HasTarget(const CStateManager& mgr) const {
if (x74_firingBeamId == CPlayerState::EBeamId::Wave)
if (auto* wb = static_cast<const CWaveBuster*>(mgr.GetObjectById(x70_waveBusterId)))
return wb->GetHomingTargetId();
return kInvalidUniqueId;
}
void CAuxWeapon::SetNewTarget(TUniqueId targetId, CStateManager& mgr) {
if (x74_firingBeamId == CPlayerState::EBeamId::Wave)
if (auto* wb = static_cast<CWaveBuster*>(mgr.ObjectById(x70_waveBusterId)))
wb->SetNewTarget(targetId);
}
} // namespace urde