From 2cf4d0586746432cd7e307fbd1556fb7d4dd2226 Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 27 Oct 2021 04:21:29 -0300 Subject: [PATCH] feat(Core/SAI): Allow forcing creatures/gameobjects's respawn timers when using SMART_ACTION_FORCE_DESPAWN (#8714) --- .../game/AI/SmartScripts/SmartScript.cpp | 20 ++++++++++--------- .../game/AI/SmartScripts/SmartScriptMgr.h | 1 + .../game/Entities/Creature/Creature.cpp | 19 +++++++++++------- src/server/game/Entities/Creature/Creature.h | 8 +++++--- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 04d03ea52..4d285fefe 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1302,20 +1302,22 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { + Milliseconds despawnDelay(e.action.forceDespawn.delay); + + // Wait at least one world update tick before despawn, so it doesn't break linked actions. + if (despawnDelay <= 0ms) + { + despawnDelay = 1ms; + } + + Seconds forceRespawnTimer(e.action.forceDespawn.forceRespawnTimer); if (Creature* creature = (*itr)->ToCreature()) { - creature->DespawnOrUnsummon(e.action.forceDespawn.delay + 1); + creature->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); } else if (GameObject* go = (*itr)->ToGameObject()) { - Milliseconds despawnDelay(e.action.forceDespawn.delay); - - // Wait at least one world update tick before despawn, so it doesn't break linked actions. - if (despawnDelay <= 0ms) - { - despawnDelay = 1ms; - } - go->DespawnOrUnsummon(despawnDelay); + go->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); } } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 93532f351..0da8dff9b 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -873,6 +873,7 @@ struct SmartAction struct { uint32 delay; + uint32 forceRespawnTimer; } forceDespawn; struct diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 32fe2e869..b0250008e 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -170,7 +170,7 @@ CreatureBaseStats const* CreatureBaseStats::GetBaseStats(uint8 level, uint8 unit bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { - m_owner.DespawnOrUnsummon(); // since we are here, we are not TempSummon as object type cannot change during runtime + m_owner.DespawnOrUnsummon(0s, m_respawnTimer); // since we are here, we are not TempSummon as object type cannot change during runtime return true; } @@ -1916,12 +1916,11 @@ void Creature::Respawn(bool force) UpdateObjectVisibility(false); } -void Creature::ForcedDespawn(uint32 timeMSToDespawn) +void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer) { if (timeMSToDespawn) { - ForcedDespawnDelayEvent* pEvent = new ForcedDespawnDelayEvent(*this); - + ForcedDespawnDelayEvent* pEvent = new ForcedDespawnDelayEvent(*this, forceRespawnTimer); m_Events.AddEvent(pEvent, m_Events.CalculateTime(timeMSToDespawn)); return; } @@ -1931,14 +1930,20 @@ void Creature::ForcedDespawn(uint32 timeMSToDespawn) // Xinef: set new respawn time, ignore corpse decay time... RemoveCorpse(true); + + if (forceRespawnTimer > Seconds::zero()) + { + m_respawnTime = time(nullptr) + forceRespawnTimer.count(); + m_respawnDelay = forceRespawnTimer.count(); + } } -void Creature::DespawnOrUnsummon(uint32 msTimeToDespawn /*= 0*/) +void Creature::DespawnOrUnsummon(Milliseconds msTimeToDespawn /*= 0*/, Seconds forcedRespawnTimer) { if (TempSummon* summon = this->ToTempSummon()) - summon->UnSummon(msTimeToDespawn); + summon->UnSummon(msTimeToDespawn.count()); else - ForcedDespawn(msTimeToDespawn); + ForcedDespawn(msTimeToDespawn.count(), forcedRespawnTimer); } void Creature::DespawnOnEvade() diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 36a37c92d..62ee4f7e1 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -267,7 +267,8 @@ public: void RemoveCorpse(bool setSpawnTime = true, bool skipVisibility = false); - void DespawnOrUnsummon(uint32 msTimeToDespawn = 0); + void DespawnOrUnsummon(Milliseconds msTimeToDespawn, Seconds forcedRespawnTimer); + void DespawnOrUnsummon(uint32 msTimeToDespawn = 0) { DespawnOrUnsummon(Milliseconds(msTimeToDespawn), 0s); }; void DespawnOnEvade(); void RespawnOnEvade(); @@ -438,7 +439,7 @@ protected: bool CanAlwaysSee(WorldObject const* obj) const override; private: - void ForcedDespawn(uint32 timeMSToDespawn = 0); + void ForcedDespawn(uint32 timeMSToDespawn = 0, Seconds forcedRespawnTimer = 0s); [[nodiscard]] bool CanPeriodicallyCallForAssistance() const; @@ -483,11 +484,12 @@ private: class ForcedDespawnDelayEvent : public BasicEvent { public: - ForcedDespawnDelayEvent(Creature& owner) : BasicEvent(), m_owner(owner) { } + ForcedDespawnDelayEvent(Creature& owner, Seconds respawnTimer) : BasicEvent(), m_owner(owner), m_respawnTimer(respawnTimer) { } bool Execute(uint64 e_time, uint32 p_time) override; private: Creature& m_owner; + Seconds const m_respawnTimer; }; #endif