diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index adfb93201..6afbd806e 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -128,19 +128,24 @@ void CreatureTemplate::InitializeQueryData() bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { - if (Unit* victim = ObjectAccessor::GetUnit(m_owner, m_victim)) + if (Unit* victim = ObjectAccessor::GetUnit(*m_owner, m_victim)) { + // Initialize last damage timer if it doesn't exist + m_owner->SetLastDamagedTime(sWorld->GetGameTime() + MAX_AGGRO_RESET_TIME); + while (!m_assistants.empty()) { - Creature* assistant = ObjectAccessor::GetCreature(m_owner, *m_assistants.begin()); + Creature* assistant = ObjectAccessor::GetCreature(*m_owner, *m_assistants.begin()); m_assistants.pop_front(); - if (assistant && assistant->CanAssistTo(&m_owner, victim)) + if (assistant && assistant->CanAssistTo(m_owner, victim)) { assistant->SetNoCallAssistance(true); assistant->CombatStart(victim); if (assistant->IsAIEnabled) assistant->AI()->AttackStart(victim); + + assistant->SetLastDamagedTimePtr(m_owner->GetLastDamagedTimePtr()); } } } @@ -163,7 +168,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_originalEquipmentId(0), m_originalAnimTier(UNIT_BYTE1_FLAG_GROUND), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false), - m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(0), m_cannotReachTarget(false), m_cannotReachTimer(0), + m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTarget(false), m_cannotReachTimer(0), _isMissingSwimmingFlagOutOfCombat(false) { m_regenTimer = CREATURE_REGEN_INTERVAL; @@ -1666,6 +1671,8 @@ void Creature::setDeathState(DeathState s, bool despawn) if (s == JUST_DIED) { + _lastDamagedTime.reset(); + m_corpseRemoveTime = time(nullptr) + m_corpseDelay; m_respawnTime = time(nullptr) + m_respawnDelay + m_corpseDelay; @@ -2098,7 +2105,7 @@ void Creature::CallAssistance() if (!assistList.empty()) { - AssistDelayEvent* e = new AssistDelayEvent(GetVictim()->GetGUID(), *this); + AssistDelayEvent* e = new AssistDelayEvent(GetVictim()->GetGUID(), this); while (!assistList.empty()) { // Pushing guids because in delay can happen some creature gets despawned => invalid pointer @@ -3152,3 +3159,34 @@ void Creature::SetCannotReachTarget(bool cannotReach) if (cannotReach) sLog->outDebug(LOG_FILTER_UNITS, "Creature::SetCannotReachTarget() called with true. Details: %s", GetDebugInfo().c_str()); } + +time_t Creature::GetLastDamagedTime() const +{ + if (!_lastDamagedTime) + return time_t(0); + + return *_lastDamagedTime; +} + +std::shared_ptr const& Creature::GetLastDamagedTimePtr() const +{ + return _lastDamagedTime; +} + +void Creature::SetLastDamagedTime(time_t val) +{ + if (val > 0) + { + if (_lastDamagedTime) + *_lastDamagedTime = val; + else + _lastDamagedTime = std::make_shared(val); + } + else + _lastDamagedTime.reset(); +} + +void Creature::SetLastDamagedTimePtr(std::shared_ptr const& val) +{ + _lastDamagedTime = val; +} diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index d4dcbc3f5..e22a88a67 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -739,8 +739,10 @@ public: bool IsMovementPreventedByCasting() const; // Part of Evade mechanics - [[nodiscard]] time_t GetLastDamagedTime() const { return _lastDamagedTime; } - void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; } + [[nodiscard]] time_t GetLastDamagedTime() const; + [[nodiscard]] std::shared_ptr const& GetLastDamagedTimePtr() const; + void SetLastDamagedTime(time_t val); + void SetLastDamagedTimePtr(std::shared_ptr const& val); bool IsFreeToMove(); static constexpr uint32 MOVE_CIRCLE_CHECK_INTERVAL = 3000; @@ -821,7 +823,7 @@ private: CreatureGroup* m_formation; bool TriggerJustRespawned; - time_t _lastDamagedTime; // Part of Evade mechanics + mutable std::shared_ptr _lastDamagedTime; // Part of Evade mechanics bool m_cannotReachTarget; uint32 m_cannotReachTimer; @@ -836,7 +838,7 @@ private: class AssistDelayEvent : public BasicEvent { public: - AssistDelayEvent(uint64 victim, Unit& owner) : BasicEvent(), m_victim(victim), m_owner(owner) { } + AssistDelayEvent(uint64 victim, Creature* owner) : BasicEvent(), m_victim(victim), m_owner(owner) { } bool Execute(uint64 e_time, uint32 p_time) override; void AddAssistant(uint64 guid) { m_assistants.push_back(guid); } @@ -845,7 +847,7 @@ private: uint64 m_victim; std::list m_assistants; - Unit& m_owner; + Creature* m_owner; }; class ForcedDespawnDelayEvent : public BasicEvent