Implement CAuxBeam

This commit is contained in:
Jack Andersen 2017-09-09 14:36:21 -10:00
parent 0907c52ca3
commit 149eed4b73
19 changed files with 709 additions and 30 deletions

View File

@ -112,6 +112,7 @@ struct CTweakPlayerGun final : ITweakPlayerGun
const SShotParam& GetBombInfo() const { return x70_bomb; }
const SShotParam& GetPowerBombInfo() const { return x8c_powerBomb; }
const SShotParam& GetMissileInfo() const { return x1d4_missile; }
};
}
}

View File

@ -123,7 +123,7 @@ void CPlayerState::PutTo(CBitStreamWriter& stream)
stream.WriteEncoded(x180_scanCompletionRate.second, CBitStreamWriter::GetBitCount(0x100));
}
static const float unk[]
static const float unk[] =
{
0.2f, 0.1f, 0.2f, 0.2f, 1.f
};
@ -133,7 +133,7 @@ float CPlayerState::sub_80091204() const
return unk[u32(x8_currentBeam)];
}
static const u32 costs[]
static const u32 costs[] =
{
5, 10, 10, 10, 1
};
@ -143,6 +143,16 @@ u32 CPlayerState::GetMissileCostForAltAttack() const
return costs[u32(x8_currentBeam)];
}
static const float ComboAmmoPeriods[] =
{
0.2f, 0.1f, 0.2f, 0.2f, 1.f
};
float CPlayerState::GetComboFireAmmoPeriod() const
{
return ComboAmmoPeriods[u32(x8_currentBeam)];
}
u32 CPlayerState::CalculateItemCollectionRate() const
{
u32 total = GetItemCapacity(EItemType::PowerBombs);

View File

@ -111,7 +111,7 @@ private:
};
union
{
struct { bool x0_24_alive : 1; bool x0_25_ : 1; bool x0_26_fusion : 1; };
struct { bool x0_24_alive : 1; bool x0_25_firingComboBeam : 1; bool x0_26_fusion : 1; };
u32 dummy = 0;
};
@ -130,6 +130,7 @@ public:
float sub_80091204() const;
u32 GetMissileCostForAltAttack() const;
float GetComboFireAmmoPeriod() const;
static constexpr float GetMissileComboChargeFactor() { return 1.8f; }
u32 CalculateItemCollectionRate() const;
@ -174,6 +175,8 @@ public:
void SetScanCompletionRate(const std::pair<u32, u32>& p) { x180_scanCompletionRate = p; }
bool IsPlayerAlive() const { return x0_24_alive; }
void SetPlayerAlive(bool alive) { x0_24_alive = alive; }
bool IsFiringComboBeam() const { return x0_25_firingComboBeam; }
void SetFiringComboBeam(bool f) { x0_25_firingComboBeam = f; }
void InitializeScanTimes();
CStaticInterference& GetStaticInterference() { return x188_staticIntf; }
const rstl::reserved_vector<std::pair<CAssetId, float>, 846>& GetScanTimes() const { return x170_scanTimes; }

View File

@ -23,11 +23,11 @@ CCameraShakerComponent CCameraShakerComponent::LoadNewCameraShakerComponent(CInp
return {flags, sp1, sp2};
}
CCameraShakeData::CCameraShakeData(float duration, float f2, u32 w1, const zeus::CVector3f& sfxPos,
CCameraShakeData::CCameraShakeData(float duration, float sfxDist, u32 w1, const zeus::CVector3f& sfxPos,
const CCameraShakerComponent& shaker1, const CCameraShakerComponent& shaker2,
const CCameraShakerComponent& shaker3)
: x0_duration(duration), x8_shaker1(shaker1), x44_shaker2(shaker2), x80_shaker3(shaker3),
xc0_flags(w1), xc4_sfxPos(sfxPos), xd0_f2(f2)
xc0_flags(w1), xc4_sfxPos(sfxPos), xd0_sfxDist(sfxDist)
{}
CCameraShakeData::CCameraShakeData(float duration, float magnitude)
@ -59,6 +59,14 @@ CCameraShakeData CCameraShakeData::BuildProjectileCameraShake(float duration, fl
CCameraShakerComponent()};
}
CCameraShakeData CCameraShakeData::BuildMissileCameraShake(float duration, float magnitude, float sfxDistance,
const zeus::CVector3f& sfxPos)
{
CCameraShakeData ret(duration, magnitude);
ret.SetSfxPositionAndDistance(sfxPos, sfxDistance);
return ret;
}
CCameraShakeData CCameraShakeData::BuildPhazonCameraShakeData(float duration, float magnitude)
{
return {duration, 100.f, 0, zeus::CVector3f::skZero,
@ -147,7 +155,7 @@ CCameraShakeData CCameraShakeData::LoadCameraShakeData(CInputStream& in)
return {duration, 100.f, 0, zeus::CVector3f::skZero, shaker1, shaker2, shaker3};
}
const CCameraShakeData CCameraShakeData::skChargedCameraShakeData =
const CCameraShakeData CCameraShakeData::skChargedShotCameraShakeData =
{0.3f, 100.f, 0, zeus::CVector3f::skZero, CCameraShakerComponent(),
CCameraShakerComponent(1, {0, 0.f, 0.f, 0.3f, -1.f}, {1, 0.f, 0.f, 0.05f, 0.3f}),
CCameraShakerComponent()};

View File

@ -48,16 +48,18 @@ class CCameraShakeData
u32 xbc_shakerId = 0;
u32 xc0_flags; // 0x1: positional sfx
zeus::CVector3f xc4_sfxPos;
float xd0_f2;
float xd0_sfxDist;
public:
static const CCameraShakeData skChargedCameraShakeData;
CCameraShakeData(float duration, float f2, u32 w1, const zeus::CVector3f& sfxPos,
static const CCameraShakeData skChargedShotCameraShakeData;
CCameraShakeData(float duration, float sfxDist, u32 w1, const zeus::CVector3f& sfxPos,
const CCameraShakerComponent& shaker1, const CCameraShakerComponent& shaker2,
const CCameraShakerComponent& shaker3);
CCameraShakeData(float duration, float magnitude);
static CCameraShakeData BuildLandingCameraShakeData(float duration, float magnitude);
static CCameraShakeData BuildProjectileCameraShake(float duration, float magnitude);
static CCameraShakeData BuildMissileCameraShake(float duration, float magnitude, float sfxDistance,
const zeus::CVector3f& sfxPos);
static CCameraShakeData BuildPhazonCameraShakeData(float duration, float magnitude);
//zeus::CVector3f GeneratePoint(float dt, CRandom16& r);
float GetSomething() const;
@ -65,6 +67,8 @@ public:
void SetShakerId(u32 id) { xbc_shakerId = id; }
u32 GetShakerId() const { return xbc_shakerId; }
static CCameraShakeData LoadCameraShakeData(CInputStream& in);
void SetSfxPositionAndDistance(const zeus::CVector3f& pos, float f2)
{ xc0_flags |= 0x1; xc4_sfxPos = pos; xd0_sfxDist = f2; }
};
}

View File

@ -10,6 +10,7 @@ enum class ERumbleFxId
Seven = 7,
Eleven = 11,
Twelve = 12,
Thirteen = 13,
Fourteen = 14,
Fifteen = 15,
Seventeen = 17

View File

@ -159,6 +159,7 @@ public:
void DestroyParticles();
void Reset() {}
FourCC Get4CharId() const { return FOURCC('SWHC'); }
void SetRenderGaps(bool r) { x1d0_27_renderGaps = r; }
void DoElectricWarmup()
{

View File

@ -1,63 +1,392 @@
#include "CAuxWeapon.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "CWaveBuster.hpp"
#include "CNewFlameThrower.hpp"
#include "CEnergyProjectile.hpp"
namespace urde
{
CAuxWeapon::CAuxWeapon(TUniqueId id)
{
static const CCameraShakeData skHardShake = { 0.3f, 100.f, 0, zeus::CVector3f::skZero,
{}, {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();
}
void CAuxWeapon::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&)
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 b1)
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);
}
}
void CAuxWeapon::Fire(bool underwater, CPlayerState::EBeamId currentBeam, EChargeState chargeState,
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, CWeapon::EProjectileAttrib::None);
mgr.AddObject(ft);
ft->Think(dt, mgr);
ft->StartFiring(xf, mgr);
x24_muzzleFxGen = std::make_unique<CElementGen>(xc_flameMuzzle,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x7c_comboSfx = NWeaponTypes::play_sfx(1842, 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(CWeapon::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,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x7c_comboSfx = NWeaponTypes::play_sfx(1847, 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,
CWeapon::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(1768);
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 | CWeapon::EProjectileAttrib::ArmCannon, underwater, zeus::CVector3f::skOne, {}, -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::Thirteen, 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;
CWeapon::EProjectileAttrib attrib = CWeapon::EProjectileAttrib::None;
if (chargeState == EChargeState::Charged)
attrib = CGameProjectile::GetBeamAttribType(type) | CWeapon::EProjectileAttrib::Unknown1;
if (chargeState == EChargeState::Normal)
{
LaunchMissile(dt, underwater, chargeState == EChargeState::Charged, 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
{
return {};
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);
}
}

View File

@ -5,22 +5,45 @@
#include "RetroTypes.hpp"
#include "CStateManager.hpp"
#include "CGunWeapon.hpp"
#include "CWeapon.hpp"
namespace urde
{
class CAuxWeapon
{
TCachedToken<CWeaponDescription> x0_missile;
TCachedToken<CGenDescription> xc_flameMuzzle;
TCachedToken<CGenDescription> x18_busterMuzzle;
std::unique_ptr<CElementGen> x24_muzzleFxGen;
rstl::reserved_vector<TCachedToken<CWeaponDescription>, 5> x28_combos;
float x68_ammoConsumeTimer = 0.f;
TUniqueId x6c_playerId;
TUniqueId x6e_flameThrowerId = kInvalidUniqueId;
TUniqueId x70_waveBusterId = kInvalidUniqueId;
CPlayerState::EBeamId x74_firingBeamId = CPlayerState::EBeamId::Invalid;
CPlayerState::EBeamId x78_loadBeamId = CPlayerState::EBeamId::Power;
CSfxHandle x7c_comboSfx;
bool x80_24_isLoaded : 1;
void InitComboData();
void FreeComboVoiceId();
void DeleteFlameThrower(CStateManager& mgr);
void CreateFlameThrower(const zeus::CTransform& xf, CStateManager& mgr, float dt);
void DeleteWaveBusterBeam(CStateManager& mgr);
void CreateWaveBusterBeam(CWeapon::EProjectileAttrib attribs, TUniqueId homingTarget,
const zeus::CTransform& xf, CStateManager& mgr);
void LaunchMissile(float dt, bool underwater, bool charged, CPlayerState::EBeamId currentBeam,
CWeapon::EProjectileAttrib attrib, const zeus::CTransform& xf, TUniqueId homingId,
CStateManager& mgr);
public:
explicit CAuxWeapon(TUniqueId id);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
explicit CAuxWeapon(TUniqueId playerId);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr);
bool IsComboFxActive(const CStateManager& mgr) const;
void Load(CPlayerState::EBeamId curBeam, CStateManager& mgr);
void StopComboFx(CStateManager& mgr, bool b1);
void StopComboFx(CStateManager& mgr, bool deactivate);
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,
void Fire(float dt, 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; }

View File

@ -20,7 +20,7 @@ class CEnergyProjectile : public CGameProjectile
bool x3d0_24_ : 1;
bool x3d0_25_ : 1;
bool x3d0_26_ : 1;
bool x3d0_27_ : 1;
bool x3d0_27_camShakeDirty : 1;
};
u32 _dummy = 0;
};
@ -32,6 +32,7 @@ public:
EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale,
const rstl::optional_object<TLockedToken<CGenDescription>>& particle,
s16 w2, bool b2);
void SetCameraShake(const CCameraShakeData& data) { x2fc_camShake = data; x3d0_27_camShakeDirty = true; }
};
}

View File

@ -16,6 +16,7 @@ class CWeaponDescription;
class CGameProjectile : public CWeapon
{
//CProjectileWeapon x170_;
TUniqueId x2c0_homingTargetId;
TUniqueId x2c8_projectileLight;
u32 x2cc_;
union
@ -45,6 +46,7 @@ public:
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
const CWeaponMode&, int) const
{ return EWeaponCollisionResponseTypes::Projectile; }
TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; }
};
}

View File

@ -245,7 +245,7 @@ void CGunWeapon::Fire(bool underwater, float dt, EChargeState chargeState, const
if (chargeState == EChargeState::Charged)
{
x218_25_enableCharge = true;
mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedCameraShakeData, false);
mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedShotCameraShakeData, false);
}
x10_solidModelData->AnimationData()->EnableLooping(false);
@ -674,7 +674,7 @@ void CGunWeapon::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32
x100_gunController->EnterFidget(mgr, s32(type), s32(x200_beamId), parm2);
}
CDamageInfo CGunWeapon::GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr) const
CDamageInfo CGunWeapon::GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr)
{
CDamageInfo ret(shotParam);
if (g_GameState->GetHardMode())

View File

@ -113,7 +113,6 @@ protected:
void FreeResPools();
void FillTokenVector(const std::vector<SObjectTag>& tags, std::vector<CToken>& objects);
void BuildDependencyList(CPlayerState::EBeamId beam);
CDamageInfo GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr) const;
void LoadSuitArm(CStateManager& mgr);
void LoadGunModels(CStateManager& mgr);
void LoadAnimations();
@ -173,6 +172,8 @@ public:
bool IsChargeAnimOver() const;
void SetDrawHologram(bool d) { x218_29_drawHologram = d; }
void EnableCharge(bool c) { x218_25_enableCharge = c; }
static CDamageInfo GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr);
};
}

View File

@ -27,6 +27,8 @@ set(WEAPON_SOURCES
CBomb.hpp CBomb.cpp
CPowerBomb.hpp CPowerBomb.cpp
CFlameInfo.hpp CFlameInfo.cpp
CFlameThrower.hpp CFlameThrower.cpp)
CFlameThrower.hpp CFlameThrower.cpp
CWaveBuster.hpp CWaveBuster.cpp
CNewFlameThrower.hpp CNewFlameThrower.cpp)
runtime_add_list(Weapon WEAPON_SOURCES)

View File

@ -0,0 +1,118 @@
#include "CNewFlameThrower.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "CStateManager.hpp"
#include "World/CGameLight.hpp"
namespace urde
{
CNewFlameThrower::CNewFlameThrower(const TToken<CWeaponDescription>& desc, const std::string& name, EWeaponType wType,
const CAssetId resInfo[8], const zeus::CTransform& xf, EMaterialTypes matType,
const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner,
EProjectileAttrib attribs)
: CGameProjectile(false, desc, name, wType, xf, matType, dInfo, uid, aid, owner, kInvalidUniqueId, attribs, false,
zeus::CVector3f::skOne, {}, -1, false),
x304_mainFire(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[0]})),
x310_mainSmoke(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[1]})),
x31c_secondarySmoke(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[4]})),
x328_secondaryFire(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[5]})),
x334_secondarySparks(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[6]})),
x340_swooshCenter(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), resInfo[2]})),
x34c_swooshFire(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), resInfo[3]}))
{
x304_mainFire.GetObj();
x310_mainSmoke.GetObj();
x31c_secondarySmoke.GetObj();
x328_secondaryFire.GetObj();
x334_secondarySparks.GetObj();
x340_swooshCenter.GetObj();
x34c_swooshFire.GetObj();
x37c_24_renderAuxEffects = false;
x37c_25_firing = false;
x37c_26_ = false;
x37c_27_ = true;
x37c_28_ = false;
x380_.resize(3);
}
void CNewFlameThrower::DeleteLightObjects(CStateManager& mgr)
{
for (TUniqueId id : x3b8_lightIds)
mgr.FreeScriptObject(id);
x3b8_lightIds.clear();
}
void CNewFlameThrower::CreateLightObjects(CStateManager& mgr)
{
DeleteLightObjects(mgr);
for (int i=0 ; i<4 ; ++i)
{
TUniqueId uid = mgr.AllocateUniqueId();
CLight lObj = x358_mainFireGen->GetLight();
CGameLight* light = new CGameLight(uid, GetAreaId(), false, "FlamethrowerLight", zeus::CTransform::Identity(),
x8_uid, lObj, u32(reinterpret_cast<uintptr_t>(this) + (i & 0x1)), 0, 0.f);
mgr.AddObject(light);
x3b8_lightIds.push_back(uid);
}
}
void CNewFlameThrower::EnableFx(CStateManager& mgr)
{
DeleteProjectileLight(mgr);
x358_mainFireGen = std::make_unique<CElementGen>(x304_mainFire,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x35c_mainSmokeGen = std::make_unique<CElementGen>(x310_mainSmoke,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x360_secondarySmokeGen = std::make_unique<CElementGen>(x31c_secondarySmoke,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x364_secondaryFireGen = std::make_unique<CElementGen>(x328_secondaryFire,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x368_secondarySparksGen = std::make_unique<CElementGen>(x334_secondarySparks,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x36c_swooshCenterGen = std::make_unique<CParticleSwoosh>(x340_swooshCenter, 0);
x36c_swooshCenterGen->SetRenderGaps(true);
x370_swooshFireGen = std::make_unique<CParticleSwoosh>(x34c_swooshFire, 0);
x370_swooshFireGen->SetRenderGaps(true);
if (x358_mainFireGen && x358_mainFireGen->SystemHasLight() && x3b8_lightIds.empty())
CreateLightObjects(mgr);
}
void CNewFlameThrower::StartFiring(const zeus::CTransform& xf, CStateManager& mgr)
{
SetActive(true);
x37c_25_firing = true;
x37c_24_renderAuxEffects = true;
x374_ = 1;
EnableFx(mgr);
}
bool CNewFlameThrower::AreEffectsFinished() const
{
if (x358_mainFireGen && x358_mainFireGen->GetParticleCount() != 0)
return false;
if (x35c_mainSmokeGen && x35c_mainSmokeGen->GetParticleCount() != 0)
return false;
if (x360_secondarySmokeGen && x360_secondarySmokeGen->GetParticleCount() != 0)
return false;
if (x364_secondaryFireGen && x364_secondaryFireGen->GetParticleCount() != 0)
return false;
return !(x368_secondarySparksGen && x368_secondarySparksGen->GetParticleCount() != 0);
}
void CNewFlameThrower::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr)
{
}
void CNewFlameThrower::Reset(CStateManager& mgr, bool deactivate)
{
}
}

View File

@ -0,0 +1,65 @@
#ifndef URDE_CNEWFLAMETHROWER_HPP
#define URDE_CNEWFLAMETHROWER_HPP
#include "CGameProjectile.hpp"
namespace urde
{
class CNewFlameThrower : public CGameProjectile
{
CRandom16 x2e8_rand = {99};
float x2ec_ = 0.f;
float x2f0_ = 0.f;
bool x300_ = false;
TCachedToken<CGenDescription> x304_mainFire;
TCachedToken<CGenDescription> x310_mainSmoke;
TCachedToken<CGenDescription> x31c_secondarySmoke;
TCachedToken<CGenDescription> x328_secondaryFire;
TCachedToken<CGenDescription> x334_secondarySparks;
TCachedToken<CSwooshDescription> x340_swooshCenter;
TCachedToken<CSwooshDescription> x34c_swooshFire;
std::unique_ptr<CElementGen> x358_mainFireGen;
std::unique_ptr<CElementGen> x35c_mainSmokeGen;
std::unique_ptr<CElementGen> x360_secondarySmokeGen;
std::unique_ptr<CElementGen> x364_secondaryFireGen;
std::unique_ptr<CElementGen> x368_secondarySparksGen;
std::unique_ptr<CParticleSwoosh> x36c_swooshCenterGen;
std::unique_ptr<CParticleSwoosh> x370_swooshFireGen;
u32 x374_ = 0;
TAreaId x378_ = kInvalidAreaId;
bool x37c_24_renderAuxEffects : 1;
bool x37c_25_firing : 1;
bool x37c_26_ : 1;
bool x37c_27_ : 1;
bool x37c_28_ : 1;
rstl::reserved_vector<std::vector<std::pair<float, u32>>, 3> x380_;
u32 x3b4_ = 0;
rstl::reserved_vector<TUniqueId, 4> x3b8_lightIds;
void DeleteLightObjects(CStateManager& mgr);
void CreateLightObjects(CStateManager& mgr);
void EnableFx(CStateManager& mgr);
public:
// Resinfo:
// NFTMainFire
// NFTMainSmoke
// NFTSwooshCenter
// NFTSwooshFire
// NFTSecondarySmoke
// NFTSecondaryFire
// NFTSecondarySparks
// <invalid>
CNewFlameThrower(const TToken<CWeaponDescription>& desc, const std::string& name, EWeaponType wType,
const CAssetId resInfo[8], const zeus::CTransform& xf, EMaterialTypes matType,
const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, EProjectileAttrib attribs);
void StartFiring(const zeus::CTransform& xf, CStateManager& mgr);
bool CanRenderAuxEffects() const { return x37c_24_renderAuxEffects; }
bool IsFiring() const { return x37c_25_firing; }
bool AreEffectsFinished() const;
void UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr);
void Reset(CStateManager& mgr, bool deactivate);
};
}
#endif // URDE_CNEWFLAMETHROWER_HPP

View File

@ -1529,7 +1529,7 @@ void CPlayerGun::FireSecondary(float dt, CStateManager& mgr)
fireXf.origin = backupOrigin;
}
fireXf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr);
x744_auxWeapon->Fire(x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf,
x744_auxWeapon->Fire(dt, x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf,
mgr, x72c_currentBeam->GetWeaponType(), targetId);
mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::Zero);
x3a0_missileExitTimer = 7.f;

View File

@ -0,0 +1,54 @@
#include "CWaveBuster.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
namespace urde
{
CWaveBuster::CWaveBuster(const TToken<CWeaponDescription>& desc, EWeaponType type, const zeus::CTransform& xf,
EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid,
TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attrib)
: CGameProjectile(true, desc, "WaveBuster", type, xf, matType, dInfo, uid, aid, owner, homingTarget, attrib, false,
zeus::CVector3f::skOne, {}, -1, false),
x2e8_originalXf(xf),
x348_targetPoint(x2e8_originalXf.basis[1].normalized() * 25.f + x2e8_originalXf.origin),
x354_busterSwoosh1(g_SimplePool->GetObj("BusterSwoosh1")),
x360_busterSwoosh2(g_SimplePool->GetObj("BusterSwoosh2")),
x36c_busterSparks(g_SimplePool->GetObj("BusterSparks")),
x378_busterLight(g_SimplePool->GetObj("BusterLight"))
{
x354_busterSwoosh1.GetObj();
x360_busterSwoosh2.GetObj();
x36c_busterSparks.GetObj();
x378_busterLight.GetObj();
x384_busterSwoosh1Gen = std::make_unique<CParticleSwoosh>(x354_busterSwoosh1, 0);
x388_busterSwoosh2Gen = std::make_unique<CParticleSwoosh>(x360_busterSwoosh2, 0);
x38c_busterSparksGen = std::make_unique<CElementGen>(x36c_busterSparks,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x390_busterLightGen = std::make_unique<CElementGen>(x378_busterLight,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x3d0_24_firing = true;
x3d0_25_ = true;
x3d0_26_ = false;
x3d0_27_ = false;
x3d0_28_ = true;
}
void CWaveBuster::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr)
{
}
void CWaveBuster::ResetBeam(bool deactivate)
{
}
void CWaveBuster::SetNewTarget(TUniqueId id)
{
}
}

View File

@ -0,0 +1,56 @@
#ifndef URDE_CWAVEBUSTER_HPP
#define URDE_CWAVEBUSTER_HPP
#include "CGameProjectile.hpp"
namespace urde
{
class CWaveBuster : public CGameProjectile
{
zeus::CTransform x2e8_originalXf;
zeus::CVector3f x318_;
zeus::CVector3f x324_;
zeus::CVector3f x330_;
zeus::CVector3f x33c_;
zeus::CVector3f x348_targetPoint;
TCachedToken<CSwooshDescription> x354_busterSwoosh1;
TCachedToken<CSwooshDescription> x360_busterSwoosh2;
TCachedToken<CGenDescription> x36c_busterSparks;
TCachedToken<CGenDescription> x378_busterLight;
std::unique_ptr<CParticleSwoosh> x384_busterSwoosh1Gen;
std::unique_ptr<CParticleSwoosh> x388_busterSwoosh2Gen;
std::unique_ptr<CElementGen> x38c_busterSparksGen;
std::unique_ptr<CElementGen> x390_busterLightGen;
CRandom16 x394_rand = {99};
float x39c_ = 0.5f;
float x3a0_ = 0.5f;
float x3a4_ = 0.f;
float x3a8_ = 0.f;
float x3ac_ = 0.f;
float x3b0_ = 0.f;
float x3b4_ = 0.f;
float x3b8_ = 0.f;
float x3bc_ = 0.f;
float x3c0_ = 0.f;
float x3c4_ = 0.f;
float x3c8_ = 0.f;
u32 x3cc_ = 0;
bool x3d0_24_firing : 1;
bool x3d0_25_ : 1;
bool x3d0_26_ : 1;
bool x3d0_27_ : 1;
bool x3d0_28_ : 1;
public:
CWaveBuster(const TToken<CWeaponDescription>& desc, EWeaponType type, const zeus::CTransform& xf,
EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid,
TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attrib);
bool IsFiring() const { return x3d0_24_firing; }
void UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr);
void ResetBeam(bool deactivate);
void SetNewTarget(TUniqueId id);
};
}
#endif // URDE_CWAVEBUSTER_HPP