From a238e5e27bfa7b0fd2f6aab19d0722c61eaf81c5 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 29 Apr 2023 06:27:13 -0400 Subject: [PATCH] fix(core\player): Missing combat animation (#14199) --- src/server/game/Entities/Unit/Unit.cpp | 10 ++++-- src/server/game/Entities/Unit/Unit.h | 14 +++++++- .../game/Spells/Auras/SpellAuraEffects.cpp | 2 +- src/server/game/World/IWorld.cpp | 35 +++++++++++++++++++ src/server/game/World/IWorld.h | 7 +++- src/server/game/World/World.cpp | 29 +++++++++++++++ src/server/game/World/World.h | 8 +++++ 7 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 src/server/game/World/IWorld.cpp diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 08bb519a6..19820d442 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -812,8 +812,14 @@ void Unit::DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb) } } -uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, bool /*allowGM*/, Spell const* damageSpell /*= nullptr*/) +uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, bool /*allowGM*/, Spell const* damageSpell /*= nullptr*/, bool delayed) { + if (delayed && attacker->GetTypeId() == TYPEID_PLAYER && attacker->GetGUID() != victim->GetGUID()) + { + sWorld->AddDelayedDamage(attacker, victim, damage, cleanDamage, damagetype, damageSchoolMask, spellProto, durabilityLoss); + return 0; + } + // Xinef: initialize damage done for rage calculations // Xinef: its rare to modify damage in hooks, however training dummy's sets damage to 0 uint32 rage_damage = damage + ((cleanDamage != nullptr) ? cleanDamage->absorbed_damage : 0); @@ -1454,7 +1460,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss, // Call default DealDamage CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, BASE_ATTACK, MELEE_HIT_NORMAL); - Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss, false, spell); + Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss, false, spell, true); } // @todo for melee need create structure as in diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 7bf605cb1..6a610a8e8 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -765,6 +765,18 @@ struct CleanDamage struct CalcDamageInfo; struct SpellNonMeleeDamage; +struct DelayedDamage +{ + Unit* attacker; + Unit* victim; + uint32 damage; + CleanDamage const* cleanDamage; + DamageEffectType damagetype; + SpellSchoolMask damageSchoolMask; + SpellInfo const* spellProto; + bool durabilityLoss; +}; + class DamageInfo { private: @@ -1575,7 +1587,7 @@ public: uint16 GetMaxSkillValueForLevel(Unit const* target = nullptr) const { return (target ? getLevelForTarget(target) : GetLevel()) * 5; } static void DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb); - static uint32 DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true, bool allowGM = false, Spell const* spell = nullptr); + static uint32 DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true, bool allowGM = false, Spell const* spell = nullptr, bool delayed = false); static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr, Spell const* spell = nullptr); void KillSelf(bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr, Spell const* spell = nullptr) { Kill(this, this, durabilityLoss, attackType, spellProto, spell); }; static int32 DealHeal(Unit* healer, Unit* victim, uint32 addhealth); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 63518fb03..7636d3ec2 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -6383,7 +6383,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit); target->SendPeriodicAuraLog(&pInfo); - Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); + Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true, false); Unit::ProcDamageAndSpell(caster, target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, &dmgInfo); } diff --git a/src/server/game/World/IWorld.cpp b/src/server/game/World/IWorld.cpp new file mode 100644 index 000000000..c29b2729d --- /dev/null +++ b/src/server/game/World/IWorld.cpp @@ -0,0 +1,35 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "IWorld.h" + +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) +{ + DelayedDamage delayedDamage; + delayedDamage.attacker = attacker; + delayedDamage.victim = victim; + delayedDamage.damage = damage; + delayedDamage.cleanDamage = cleanDamage; + delayedDamage.damagetype = damagetype; + delayedDamage.damageSchoolMask = damageSchoolMask; + delayedDamage.spellProto = spellProto; + delayedDamage.durabilityLoss = durabilityLoss; + _delayedDamages.push_back(delayedDamage); +} diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index c5fff797b..236051d15 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -24,15 +24,17 @@ #include "ObjectGuid.h" #include "QueryResult.h" #include "SharedDefines.h" +#include "Unit.h" #include #include #include #include #include +class IWorld; +class Player; class WorldPacket; class WorldSession; -class Player; /// Storage class for commands issued for delayed execution struct AC_GAME_API CliCommandHolder @@ -516,10 +518,13 @@ enum Rates class IWorld { public: + std::list _delayedDamages; + virtual ~IWorld() = default; [[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 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 99bb33611..0b8a57d0a 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2064,6 +2064,8 @@ void World::SetInitialWorldSettings() _mail_expire_check_timer = GameTime::GetGameTime() + 6h; + _timers[WUPDATE_DELAYED_DAMAGES].SetInterval(400); + ///- Initialize MapMgr LOG_INFO("server.loading", "Starting Map System"); LOG_INFO("server.loading", " "); @@ -2310,6 +2312,12 @@ void World::Update(uint32 diff) { METRIC_TIMER("world_update_time", METRIC_TAG("type", "Check quest reset times")); + if (_timers[WUPDATE_DELAYED_DAMAGES].Passed()) + { + _timers[WUPDATE_DELAYED_DAMAGES].Reset(); + ProcessDelayedDamages(); + } + /// Handle daily quests reset time if (currentGameTime > _nextDailyQuestReset) { @@ -3331,3 +3339,24 @@ 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) +{ + DelayedDamage delayedDamage; + delayedDamage.attacker = attacker; + delayedDamage.victim = victim; + delayedDamage.damage = damage; + delayedDamage.cleanDamage = cleanDamage; + delayedDamage.damagetype = damagetype; + delayedDamage.damageSchoolMask = damageSchoolMask; + delayedDamage.spellProto = spellProto; + delayedDamage.durabilityLoss = durabilityLoss; + _delayedDamages.push_back(delayedDamage); +} + +void World::ProcessDelayedDamages() +{ + for (auto& damage : _delayedDamages) + Unit::DealDamage(damage.attacker, damage.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 f8e0de9b8..222a5586f 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -28,6 +28,7 @@ #include "QueryResult.h" #include "SharedDefines.h" #include "Timer.h" +#include "Unit.h" #include #include #include @@ -70,6 +71,7 @@ enum WorldTimers WUPDATE_PINGDB, WUPDATE_5_SECS, WUPDATE_WHO_LIST, + WUPDATE_DELAYED_DAMAGES, WUPDATE_COUNT }; @@ -153,6 +155,8 @@ public: World(); ~World() override; + std::list _delayedDamages; + static World* instance(); static uint32 m_worldLoopCounter; @@ -351,6 +355,10 @@ 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 ProcessDelayedDamages(); + protected: void _UpdateGameTime(); // callback for UpdateRealmCharacters