diff --git a/Runtime/MP1/World/CElitePirate.cpp b/Runtime/MP1/World/CElitePirate.cpp index 6a9232867..431592b8b 100644 --- a/Runtime/MP1/World/CElitePirate.cpp +++ b/Runtime/MP1/World/CElitePirate.cpp @@ -596,7 +596,30 @@ void CElitePirate::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) { } } -void CElitePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) { CAi::SpecialAttack(mgr, msg, dt); } +void CElitePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = EState::Zero; + } else if (msg == EStateMsg::Update) { + if (x568_ == EState::Zero) { + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) { + x568_ = EState::Two; + x988_29_ = true; + } else { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCProjectileAttackCmd(pas::ESeverity::Two, mgr.GetPlayer().GetTranslation(), false)); + } + } else if (x568_ == EState::Two) { + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) { + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation()); + } else { + x568_ = EState::Over; + } + } + } else if (msg == EStateMsg::Deactivate) { + sub_802285c4(mgr); + x988_29_ = false; + } +} void CElitePirate::CallForBackup(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { diff --git a/Runtime/MP1/World/CShockWave.cpp b/Runtime/MP1/World/CShockWave.cpp index 4d55b753f..96e040da5 100644 --- a/Runtime/MP1/World/CShockWave.cpp +++ b/Runtime/MP1/World/CShockWave.cpp @@ -1,15 +1,16 @@ #include "Runtime/MP1/World/CShockWave.hpp" +#include "Runtime/Collision/CCollisionActor.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/CStateManager.hpp" #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Graphics/CBooRenderer.hpp" #include "Runtime/World/CActorParameters.hpp" +#include "Runtime/World/CGameLight.hpp" #include "TCastTo.hpp" // Generated file, do not modify include path -namespace urde { -namespace MP1 { +namespace urde::MP1 { CShockWave::CShockWave(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, TUniqueId parent, const SShockWaveData& data, float f1, float f2) : CActor(uid, true, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::Projectile}, @@ -35,8 +36,19 @@ CShockWave::CShockWave(TUniqueId uid, std::string_view name, const CEntityInfo& void CShockWave::Accept(IVisitor& visitor) { visitor.Visit(this); } void CShockWave::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { - // TODO + if (msg == EScriptObjectMessage::Registered) { + if (x110_elementGen->SystemHasLight()) { + x980_id2 = mgr.AllocateUniqueId(); + mgr.AddObject(new CGameLight(x980_id2, GetAreaIdAlways(), GetActive(), "ShockWaveLight_" + x10_name, + GetTransform(), GetUniqueId(), x110_elementGen->GetLight(), + x114_data.x4_particleDesc.Value(), 1, 0.f)); + } + } else if (msg == EScriptObjectMessage::Deleted) { + mgr.FreeScriptObject(x980_id2); + x980_id2 = kInvalidUniqueId; + } CActor::AcceptScriptMsg(msg, uid, mgr); + mgr.SendScriptMsgAlways(x980_id2, uid, msg); } void CShockWave::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { @@ -45,8 +57,10 @@ void CShockWave::AddToRenderer(const zeus::CFrustum& frustum, const CStateManage } std::optional CShockWave::GetTouchBounds() const { - // TODO - return CActor::GetTouchBounds(); + if (x150_ <= 0.f) { + return std::nullopt; + } + return zeus::CAABox({-x150_, -x150_, 0.f}, {x150_, x150_, 1.f}).getTransformedAABox(GetTransform()); } void CShockWave::Render(const CStateManager& mgr) const { @@ -55,11 +69,49 @@ void CShockWave::Render(const CStateManager& mgr) const { } void CShockWave::Think(float dt, CStateManager& mgr) { - // TODO + if (GetActive()) { + x110_elementGen->Update(dt); + x158_ += dt; + x150_ += x154_ * dt; + x154_ += dt * x114_data.x30_; + x110_elementGen->SetExternalVar(0, x150_); + for (int i = 0; i < x110_elementGen->GetNumActiveChildParticles(); i++) { + auto& particle = static_cast(x110_elementGen->GetActiveChildParticle(i)); + if (particle.Get4CharId() == SBIG('PART')) { + particle.SetExternalVar(0, x150_); + } + } + if (x16c_) { + x164_ += dt; + x16c_ = false; + } + if (x16d_) { + x168_ += dt; + x16d_ = false; + } + } + if (x110_elementGen->IsSystemDeletable() && x15c_ > 0.f && x158_ >= x15c_) { + mgr.FreeScriptObject(GetUniqueId()); + } else if (x980_id2 != kInvalidUniqueId) { + if (TCastToPtr light = mgr.ObjectById(x980_id2)) { + if (light->GetActive()) { + light->SetLight(x110_elementGen->GetLight()); + } + } + } } void CShockWave::Touch(CActor& actor, CStateManager& mgr) { - // TODO + if (x158_ >= x15c_) { + return; + } + + bool isParent = xe8_id1 == actor.GetUniqueId(); + if (TCastToConstPtr cactor = mgr.GetObjectById(actor.GetUniqueId())) { + isParent = xe8_id1 == cactor->GetOwnerId(); + } + if (!isParent) { + // TODO + } } -} // namespace MP1 -} // namespace urde +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CShockWave.hpp b/Runtime/MP1/World/CShockWave.hpp index 19e3e479a..f5a8d2336 100644 --- a/Runtime/MP1/World/CShockWave.hpp +++ b/Runtime/MP1/World/CShockWave.hpp @@ -4,8 +4,7 @@ #include "Runtime/World/CDamageInfo.hpp" #include "Runtime/Particle/CElementGen.hpp" -namespace urde { -namespace MP1 { +namespace urde::MP1 { struct SShockWaveData { u32 x0_ = 8; CAssetId x4_particleDesc; @@ -22,7 +21,7 @@ struct SShockWaveData { }; class CShockWave : public CActor { -public: +private: TUniqueId xe8_id1; CDamageInfo xec_damageInfo; TToken x108_elementGenDesc; @@ -35,22 +34,22 @@ public: float x160_; float x164_ = 0.f; float x168_ = 0.f; - char x16c_flags1; - char x16d_flags2; + bool x16c_ = false; + bool x16d_ = false; // x368 => very large reserved_vector of ? std::optional> x974_electricDesc; TUniqueId x980_id2 = kInvalidUniqueId; +public: CShockWave(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, TUniqueId parent, const SShockWaveData& data, float f1, float f2); void Accept(IVisitor& visitor) override; void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override; - std::optional GetTouchBounds() const override; + [[nodiscard]] std::optional GetTouchBounds() const override; void Render(const CStateManager& mgr) const override; void Think(float dt, CStateManager& mgr) override; void Touch(CActor& actor, CStateManager& mgr) override; }; -} // namespace MP1 } // namespace urde