From ba9105873632d758490e170aced6843e75c40f2f Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 18 Oct 2023 07:17:57 -0700 Subject: [PATCH] Destroyable: Fix animated deaths (#1227) Fixes #1222 addresses an issue where the death behavior of a destructible component was not being respected and enemies with destroyable components that had special death animations were not able to play the animation on death. This pr adds in the hardcoded constant the client uses for the same metric of 12 seconds. Tested that claiming Nimbus Rock and completing the property guards mission allows him to vacuum away and then network the destruction packet 12 seconds later. --- dGame/Entity.cpp | 13 ++++++++++++- dGame/dComponents/DestroyableComponent.cpp | 1 + dGame/dComponents/DestroyableComponent.h | 8 ++++++++ dScripts/ai/PROPERTY/AgPropguards.cpp | 2 +- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 80eec04f..52b34931 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -373,6 +373,7 @@ void Entity::Initialize() { comp->SetMaxHealth(destCompData[0].life); comp->SetMaxImagination(destCompData[0].imagination); comp->SetMaxArmor(destCompData[0].armor); + comp->SetDeathBehavior(destCompData[0].death_behavior); comp->SetIsSmashable(destCompData[0].isSmashable); @@ -1561,7 +1562,17 @@ void Entity::Kill(Entity* murderer) { } if (!IsPlayer()) { - Game::entityManager->DestroyEntity(this); + auto* destroyableComponent = GetComponent(); + bool waitForDeathAnimation = false; + + if (destroyableComponent) { + waitForDeathAnimation = destroyableComponent->GetDeathBehavior() == 0; + } + + // Live waited a hard coded 12 seconds for death animations of type 0 before networking destruction! + constexpr float DelayDeathTime = 12.0f; + if (waitForDeathAnimation) AddCallbackTimer(DelayDeathTime, [this]() { Game::entityManager->DestroyEntity(this); }); + else Game::entityManager->DestroyEntity(this); } const auto& grpNameQBShowBricks = GetVar(u"grpNameQBShowBricks"); diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 06fc8848..163d2dc6 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -72,6 +72,7 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) { m_ImmuneToImaginationLossCount = 0; m_ImmuneToQuickbuildInterruptCount = 0; m_ImmuneToPullToPointCount = 0; + m_DeathBehavior = -1; } DestroyableComponent::~DestroyableComponent() { diff --git a/dGame/dComponents/DestroyableComponent.h b/dGame/dComponents/DestroyableComponent.h index d9a2191d..46af3922 100644 --- a/dGame/dComponents/DestroyableComponent.h +++ b/dGame/dComponents/DestroyableComponent.h @@ -416,6 +416,9 @@ public: const bool GetImmuneToQuickbuildInterrupt() {return m_ImmuneToQuickbuildInterruptCount > 0;}; const bool GetImmuneToPullToPoint() {return m_ImmuneToPullToPointCount > 0;}; + int32_t GetDeathBehavior() const { return m_DeathBehavior; } + void SetDeathBehavior(int32_t value) { m_DeathBehavior = value; } + /** * Utility to reset all stats to the default stats based on items and completed missions */ @@ -597,6 +600,11 @@ private: uint32_t m_ImmuneToImaginationLossCount; uint32_t m_ImmuneToQuickbuildInterruptCount; uint32_t m_ImmuneToPullToPointCount; + + /** + * Death behavior type. If 0, the client plays a death animation as opposed to a smash animation. + */ + int32_t m_DeathBehavior; }; #endif // DESTROYABLECOMPONENT_H diff --git a/dScripts/ai/PROPERTY/AgPropguards.cpp b/dScripts/ai/PROPERTY/AgPropguards.cpp index c514031a..ced7dd68 100644 --- a/dScripts/ai/PROPERTY/AgPropguards.cpp +++ b/dScripts/ai/PROPERTY/AgPropguards.cpp @@ -18,7 +18,7 @@ void AgPropguards::OnMissionDialogueOK(Entity* self, Entity* target, int mission && !character->GetPlayerFlag(flag)) { // If the player just started the mission, play a cinematic highlighting the target GameMessages::SendPlayCinematic(target->GetObjectID(), u"MissionCam", target->GetSystemAddress()); - } else if (missionState == eMissionState::COMPLETE_READY_TO_COMPLETE) { + } else if (missionState == eMissionState::READY_TO_COMPLETE) { // Makes the guard disappear once the mission has been completed const auto zoneControlID = Game::entityManager->GetZoneControlEntity()->GetObjectID(); GameMessages::SendNotifyClientObject(zoneControlID, u"GuardChat", 0, 0, self->GetObjectID(),