diff --git a/Runtime/Particle/CParticleElectric.cpp b/Runtime/Particle/CParticleElectric.cpp index cceda30a1..00710a5ca 100644 --- a/Runtime/Particle/CParticleElectric.cpp +++ b/Runtime/Particle/CParticleElectric.cpp @@ -625,7 +625,7 @@ bool CParticleElectric::Update(double dt) return ret; } -void CParticleElectric::Render(const CActorLights*) +void CParticleElectric::Render(const CActorLights* lights) { if (x3e8_electricManagers.size()) { @@ -640,13 +640,13 @@ void CParticleElectric::Render(const CActorLights*) if (x450_25_haveGPSM) { for (int i=0 ; iRender(); + x400_gpsmGenerators[i]->Render(lights); } if (x450_26_haveEPSM) { for (int i=0 ; iRender(); + x410_epsmGenerators[i]->Render(lights); } } diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index ef5505081..da7b3d52e 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -2624,11 +2624,11 @@ TUniqueId CPlayerGun::DropPowerBomb(CStateManager& mgr) : CDamageInfo(CWeaponMode::PowerBomb(), 0.f, 0.f, 0.f)); TUniqueId uid = mgr.AllocateUniqueId(); - CPowerBomb* pBomb = - new CPowerBomb(x784_bombEffects[1][0], uid, kInvalidAreaId, x538_playerId, - zeus::CTransform::Translate(mgr.GetPlayer().GetTranslation() + - zeus::CVector3f{0.f, g_tweakPlayer->GetPlayerBallHalfExtent(), 0.f}), - dInfo); + zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation(); + zeus::CTransform xf = zeus::CTransform::Translate({plVec.x, + plVec.y, + plVec.z + g_tweakPlayer->GetPlayerBallHalfExtent()}); + CPowerBomb* pBomb = new CPowerBomb(x784_bombEffects[1][0], uid, kInvalidAreaId, x538_playerId, xf, dInfo); mgr.AddObject(*pBomb); return uid; } diff --git a/Runtime/Weapon/CPowerBomb.cpp b/Runtime/Weapon/CPowerBomb.cpp index dae662c6c..34f316a8b 100644 --- a/Runtime/Weapon/CPowerBomb.cpp +++ b/Runtime/Weapon/CPowerBomb.cpp @@ -1,8 +1,19 @@ #include "CPowerBomb.hpp" +#include "Runtime/Particle/CElementGen.hpp" +#include "World/CDamageInfo.hpp" +#include "CStateManager.hpp" +#include "GameGlobalObjects.hpp" +#include "Graphics/CBooRenderer.hpp" +#include "CPlayerState.hpp" +#include "World/CPlayer.hpp" +#include "DataSpec/DNAMP1/SFX/Weapons.h" +#include "TCastTo.hpp" namespace urde { +const zeus::CColor CPowerBomb::kFadeColor(COLOR(0xffffff7)); + CPowerBomb::CPowerBomb(const TToken& particle, TUniqueId uid, TAreaId aid, TUniqueId playerId, const zeus::CTransform& xf, const CDamageInfo& dInfo) : CWeapon(uid, aid, true, playerId, EWeaponType::PowerBomb, "PowerBomb", xf, @@ -11,8 +22,97 @@ CPowerBomb::CPowerBomb(const TToken& particle, TUniqueId uid, T {EMaterialTypes::Projectile, EMaterialTypes::PowerBomb}), {EMaterialTypes::Projectile, EMaterialTypes::PowerBomb}, dInfo, EProjectileAttrib::PowerBombs, CModelData::CModelDataNull()) +, x158_24_canStartFilter(true) +, x158_25_filterEnabled(false) +, x164_radiusIncrement(dInfo.GetRadius() / 2.5f) +, x168_particle(new CElementGen(particle)) +, x16c_radius(dInfo.GetRadius()) { + x168_particle->SetGlobalTranslation(GetTranslation()); +} +void CPowerBomb::Accept(IVisitor& visitor) +{ + visitor.Visit(this); +} + +void CPowerBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) +{ + if (msg == EScriptObjectMessage::Registered) + { + mgr.AddWeaponId(xec_ownerId, xf0_weaponType); + if (mgr.GetPlayerState()->IsPlayerAlive()) + { + CSfxManager::AddEmitter(SFXsfx0710, GetTranslation(), {}, true, false, 0x7f, -1); + mgr.InformListeners(GetTranslation(), EListenNoiseType::Bomb); + } + else + { + auto handle = CSfxManager::AddEmitter(SFXsfx073F, GetTranslation(), {}, true, false, 0x7f, -1); + mgr.Player()->ApplySubmergedPitchBend(handle); + } + } + else if (msg == EScriptObjectMessage::Deleted) + { + if (x15c_curTime > 0.7f) + mgr.GetCameraFilterPass(6).DisableFilter(0.f); + + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); + } + CActor::AcceptScriptMsg(msg, uid, mgr); +} + +void CPowerBomb::Think(float dt, CStateManager& mgr) +{ + CWeapon::Think(dt, mgr); + if (x158_24_canStartFilter) + { + if (x15c_curTime > 1.f && !x158_25_filterEnabled) + { + mgr.GetCameraFilterPass(6).SetFilter(EFilterType::Add, EFilterShape::Fullscreen, 1.5f, kFadeColor, -1); + x158_25_filterEnabled = true; + } + + if (x15c_curTime > 2.5f) + x158_24_canStartFilter = false; + } + else if (x15c_curTime > 3.75 && x158_25_filterEnabled) + { + mgr.GetCameraFilterPass(6).DisableFilter(.5f); + x158_25_filterEnabled = false; + } + + if (x15c_curTime > 7.f) + { + if (x168_particle->IsSystemDeletable()) + mgr.FreeScriptObject(GetUniqueId()); + } + + if (x15c_curTime > 30.f) + { + mgr.FreeScriptObject(GetUniqueId()); + return; + } + + if (x15c_curTime > 1.f && x15c_curTime < 4.f) + { + x110_origDamageInfo.SetRadius(x160_curRadius); + ApplyDynamicDamage(GetTranslation(), mgr); + x160_curRadius += x164_radiusIncrement; + } + + x168_particle->Update(dt); + x15c_curTime += dt; +} + +void CPowerBomb::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const +{ + g_Renderer->AddParticleGen(*x168_particle); +} + +void CPowerBomb::ApplyDynamicDamage(const zeus::CVector3f& pos, urde::CStateManager& mgr) +{ + mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter); } } diff --git a/Runtime/Weapon/CPowerBomb.hpp b/Runtime/Weapon/CPowerBomb.hpp index b2db7e59d..ec9f2ca13 100644 --- a/Runtime/Weapon/CPowerBomb.hpp +++ b/Runtime/Weapon/CPowerBomb.hpp @@ -7,14 +7,30 @@ namespace urde { +class CElementGen; class CPowerBomb : public CWeapon { + static const zeus::CColor kFadeColor; + bool x158_24_canStartFilter : 1; + bool x158_25_filterEnabled : 1; float x15c_curTime = 0.f; - float x160_ = 0.f; + float x160_curRadius = 0.f; + float x164_radiusIncrement; + std::unique_ptr x168_particle; + float x16c_radius; public: CPowerBomb(const TToken& particle, TUniqueId uid, TAreaId aid, TUniqueId playerId, const zeus::CTransform& xf, const CDamageInfo& dInfo); + + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const {} + std::experimental::optional GetTouchBounds() const { return {}; } + void Touch(CActor&, CStateManager&) { /*x158_24_canStartFilter; */} float GetCurTime() const { return x15c_curTime; } + void ApplyDynamicDamage(const zeus::CVector3f&, CStateManager&); }; } diff --git a/Runtime/World/CScriptEffect.cpp b/Runtime/World/CScriptEffect.cpp index df112c3f8..3a2163344 100644 --- a/Runtime/World/CScriptEffect.cpp +++ b/Runtime/World/CScriptEffect.cpp @@ -278,7 +278,7 @@ void CScriptEffect::Render(const CStateManager& mgr) const if (xf4_electric && xf4_electric->GetParticleCount() > 0) { g_NumParticlesRendered += xf4_electric->GetParticleCount(); - xf4_electric->Render(); + xf4_electric->Render(GetActorLights()); } } diff --git a/Runtime/World/CScriptSpawnPoint.cpp b/Runtime/World/CScriptSpawnPoint.cpp index 6c3589daa..6c181f886 100644 --- a/Runtime/World/CScriptSpawnPoint.cpp +++ b/Runtime/World/CScriptSpawnPoint.cpp @@ -13,11 +13,14 @@ CScriptSpawnPoint::CScriptSpawnPoint(TUniqueId uid, std::string_view name, const bool defaultSpawn, bool active, bool morphed) : CEntity(uid, info, active, name), x34_xf(xf), x64_itemCounts(itemCounts) { +#ifndef NDEBUG x64_itemCounts[int(CPlayerState::EItemType::ThermalVisor)] = 1; x64_itemCounts[int(CPlayerState::EItemType::XRayVisor)] = 1; x64_itemCounts[int(CPlayerState::EItemType::GrappleBeam)] = 1; x64_itemCounts[int(CPlayerState::EItemType::BoostBall)] = 1; x64_itemCounts[int(CPlayerState::EItemType::ChargeBeam)] = 1; + x64_itemCounts[int(CPlayerState::EItemType::PowerBombs)] = 1; +#endif x10c_24_firstSpawn = defaultSpawn; x10c_25_morphed = morphed; }