From a4e2b1d743bfd9e63e51c04c49959fa76691069c Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Fri, 13 Dec 2024 08:50:45 +0100 Subject: [PATCH] feat(Core/WorldObjects): implement Heartbeat timers (#20872) --- .../game/Entities/GameObject/GameObject.cpp | 2 ++ src/server/game/Entities/Object/Object.cpp | 17 ++++++++++++++--- src/server/game/Entities/Object/Object.h | 11 +++++++++-- src/server/game/Entities/Unit/Unit.cpp | 3 +-- src/server/game/Entities/Unit/Unit.h | 3 --- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 5cf90d71a..163e390f2 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -446,6 +446,8 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u void GameObject::Update(uint32 diff) { + WorldObject::Update(diff); + if (AI()) AI()->UpdateAI(diff); else if (!AIM_Initialize()) diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index b37efedca..317b3441c 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1050,7 +1050,7 @@ void MovementInfo::OutDebug() WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0), m_name(""), m_isActive(false), m_visibilityDistanceOverride(), m_isWorldObject(isWorldObject), m_zoneScript(nullptr), _zoneId(0), _areaId(0), _floorZ(INVALID_HEIGHT), _outdoors(false), _liquidData(), _updatePositionData(false), m_transport(nullptr), - m_currMap(nullptr), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_useCombinedPhases(true), m_notifyflags(0), m_executed_notifies(0) + m_currMap(nullptr), _heartbeatTimer(HEARTBEAT_INTERVAL), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_useCombinedPhases(true), m_notifyflags(0), m_executed_notifies(0) { m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST); m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); @@ -1058,9 +1058,18 @@ WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), sScriptMgr->OnWorldObjectCreate(this); } -void WorldObject::Update(uint32 time_diff) +void WorldObject::Update(uint32 diff) { - sScriptMgr->OnWorldObjectUpdate(this, time_diff); + m_Events.Update(diff); + + _heartbeatTimer -= Milliseconds(diff); + while (_heartbeatTimer <= 0ms) + { + _heartbeatTimer += HEARTBEAT_INTERVAL; + Heartbeat(); + } + + sScriptMgr->OnWorldObjectUpdate(this, diff); } void WorldObject::SetWorldObject(bool on) @@ -1134,6 +1143,8 @@ void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/) { if (IsInWorld()) RemoveFromWorld(); + + m_Events.KillAllEvents(false); // non-delatable (currently cast spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList } void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 phaseMask) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index e0792f840..c0b7239a2 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -20,6 +20,7 @@ #include "Common.h" #include "DataMap.h" +#include "EventProcessor.h" #include "G3D/Vector3.h" #include "GridDefines.h" #include "GridReference.h" @@ -96,6 +97,8 @@ struct PositionFullTerrainStatus; typedef std::unordered_map UpdateDataMapType; typedef GuidUnorderedSet UpdatePlayerSet; +static constexpr Milliseconds HEARTBEAT_INTERVAL = 5s + 200ms; + class Object { public: @@ -220,6 +223,8 @@ public: [[nodiscard]] inline bool IsItem() const { return GetTypeId() == TYPEID_ITEM; } + virtual void Heartbeat() {} + virtual std::string GetDebugInfo() const; DataMap CustomData; @@ -408,7 +413,7 @@ protected: public: ~WorldObject() override; - virtual void Update(uint32 /*time_diff*/); + virtual void Update(uint32 diff); void _Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 phaseMask); @@ -632,7 +637,9 @@ public: std::string GetDebugInfo() const override; + // Event handler ElunaEventProcessor* elunaEvents; + EventProcessor m_Events; protected: std::string m_name; @@ -666,7 +673,7 @@ protected: virtual bool IsAlwaysDetectableFor(WorldObject const* /*seer*/) const { return false; } private: Map* m_currMap; //current object's Map location - + Milliseconds _heartbeatTimer; //uint32 m_mapId; // object at map with map_id uint32 m_InstanceId; // in map copy with instance id uint32 m_phaseMask; // in area phase state diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f5f299625..c5cc5b808 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -386,7 +386,7 @@ void Unit::Update(uint32 p_time) // WARNING! Order of execution here is important, do not change. // Spells must be processed with event system BEFORE they go to _UpdateSpells. // Or else we may have some SPELL_STATE_FINISHED spells stalled in pointers, that is bad. - m_Events.Update(p_time); + WorldObject::Update(p_time); if (!IsInWorld()) return; @@ -15760,7 +15760,6 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup) if (finalCleanup) m_cleanupDone = true; - m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList CombatStop(); ClearComboPoints(); ClearComboPointHolders(); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index af6c71e41..47a6af78d 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1952,9 +1952,6 @@ public: float m_threatModifier[MAX_SPELL_SCHOOL]; float m_modAttackSpeedPct[3]; - // Event handler - EventProcessor m_Events; - SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; uint32 m_lastSanctuaryTime;