From d282cce4af69110fa035954b3c81258a1e560b5e Mon Sep 17 00:00:00 2001 From: Angelo Venturini Date: Sun, 7 May 2023 08:58:38 -0300 Subject: [PATCH] fix(Core/Spells): Delayed Damage system (#16183) --- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Entities/Unit/Unit.h | 6 ++++-- src/server/game/Globals/ObjectAccessor.cpp | 11 +++++++++++ src/server/game/Globals/ObjectAccessor.h | 1 + src/server/game/World/IWorld.cpp | 4 +++- src/server/game/World/IWorld.h | 2 +- src/server/game/World/World.cpp | 16 +++++++++++++--- src/server/game/World/World.h | 2 +- 8 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 219a1e274..b3d7086e9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -816,7 +816,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage { if (delayed && attacker && attacker->GetTypeId() == TYPEID_PLAYER && attacker->GetGUID() != victim->GetGUID()) { - sWorld->AddDelayedDamage(attacker, victim, damage, cleanDamage, damagetype, damageSchoolMask, spellProto, durabilityLoss); + sWorld->AddDelayedDamage(attacker->GetGUID(), victim->GetGUID(), damage, cleanDamage, damagetype, damageSchoolMask, spellProto, durabilityLoss, attacker->GetMapId(), attacker->GetInstanceId()); return 0; } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 3213c01b9..430029611 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -759,14 +759,16 @@ struct SpellNonMeleeDamage; struct DelayedDamage { - Unit* attacker; - Unit* victim; + ObjectGuid attacker; + ObjectGuid victim; uint32 damage; CleanDamage const* cleanDamage; DamageEffectType damagetype; SpellSchoolMask damageSchoolMask; SpellInfo const* spellProto; bool durabilityLoss; + uint32 mapId; + uint32 instanceId; }; class DamageInfo diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index a529e4e00..f2ef95526 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -212,6 +212,17 @@ Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid const guid) return GetCreature(u, guid); } +Unit* ObjectAccessor::GetUnit(Map const* map, ObjectGuid const guid) +{ + if (guid.IsPlayer()) + return GetPlayer(map, guid); + + if (guid.IsPet()) + return const_cast(map)->GetPet(guid); + + return const_cast(map)->GetCreature(guid); +} + Creature* ObjectAccessor::GetCreature(WorldObject const& u, ObjectGuid const guid) { return u.GetMap()->GetCreature(guid); diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h index 7c6c003f5..8532dba74 100644 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -71,6 +71,7 @@ namespace ObjectAccessor Transport* GetTransport(WorldObject const& u, ObjectGuid const guid); DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const guid); Unit* GetUnit(WorldObject const&, ObjectGuid const guid); + Unit* GetUnit(Map const* map, ObjectGuid const guid); Creature* GetCreature(WorldObject const& u, ObjectGuid const guid); Pet* GetPet(WorldObject const&, ObjectGuid const guid); Player* GetPlayer(Map const*, ObjectGuid const guid); diff --git a/src/server/game/World/IWorld.cpp b/src/server/game/World/IWorld.cpp index c29b2729d..ae421903a 100644 --- a/src/server/game/World/IWorld.cpp +++ b/src/server/game/World/IWorld.cpp @@ -20,7 +20,7 @@ class Unit; class IWorld; -void IWorld::AddDelayedDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss) +void IWorld::AddDelayedDamage(ObjectGuid attacker, ObjectGuid victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, uint32 mapId, uint32 instanceId) { DelayedDamage delayedDamage; delayedDamage.attacker = attacker; @@ -31,5 +31,7 @@ void IWorld::AddDelayedDamage(Unit* attacker, Unit* victim, uint32 damage, Clean delayedDamage.damageSchoolMask = damageSchoolMask; delayedDamage.spellProto = spellProto; delayedDamage.durabilityLoss = durabilityLoss; + delayedDamage.mapId = mapId; + delayedDamage.instanceId = instanceId; _delayedDamages.push_back(delayedDamage); } diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 236051d15..1d4a6f0fe 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -524,7 +524,7 @@ public: [[nodiscard]] virtual WorldSession* FindSession(uint32 id) const = 0; [[nodiscard]] virtual WorldSession* FindOfflineSession(uint32 id) const = 0; [[nodiscard]] virtual WorldSession* FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const = 0; - virtual void AddDelayedDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss); + virtual void AddDelayedDamage(ObjectGuid attacker, ObjectGuid victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, uint32 mapId, uint32 instanceId); virtual void AddSession(WorldSession* s) = 0; virtual bool KickSession(uint32 id) = 0; virtual void UpdateMaxSessionCounters() = 0; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 1488c39d5..621cfc056 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -3340,7 +3340,7 @@ CliCommandHolder::~CliCommandHolder() free(m_command); } -void World::AddDelayedDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss) +void World::AddDelayedDamage(ObjectGuid attacker, ObjectGuid victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, uint32 mapId, uint32 instanceId) { DelayedDamage delayedDamage; delayedDamage.attacker = attacker; @@ -3351,6 +3351,8 @@ void World::AddDelayedDamage(Unit* attacker, Unit* victim, uint32 damage, CleanD delayedDamage.damageSchoolMask = damageSchoolMask; delayedDamage.spellProto = spellProto; delayedDamage.durabilityLoss = durabilityLoss; + delayedDamage.mapId = mapId; + delayedDamage.instanceId = instanceId; _delayedDamages.push_back(delayedDamage); } @@ -3358,10 +3360,18 @@ void World::ProcessDelayedDamages() { for (auto& damage : _delayedDamages) { - if (!damage.victim) + // Get map first + Map* map = sMapMgr->FindMap(damage.mapId, damage.instanceId); + if (!map) continue; - Unit::DealDamage(damage.attacker, damage.victim, damage.damage, damage.cleanDamage, damage.damagetype, damage.damageSchoolMask, damage.spellProto, damage.durabilityLoss); + // Now we get both, attacker and victim, but attacker can be null (although attacker is always a player). + Unit* attacker = ObjectAccessor::GetUnit(map, damage.attacker); + Unit* victim = ObjectAccessor::GetUnit(map, damage.victim); + if (!victim) + continue; + + Unit::DealDamage(attacker, victim, damage.damage, damage.cleanDamage, damage.damagetype, damage.damageSchoolMask, damage.spellProto, damage.durabilityLoss); } _delayedDamages.clear(); } diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 222a5586f..590d85161 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -355,7 +355,7 @@ public: void RemoveOldCorpses() override; - void AddDelayedDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss) override; + void AddDelayedDamage(ObjectGuid attacker, ObjectGuid victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, uint32 mapId, uint32 instanceId) override; void ProcessDelayedDamages();