From 478fbe9fc1783adaa8834b5429dd4725216be818 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Mon, 16 Mar 2020 16:17:41 +0100 Subject: [PATCH] Core/Spells: implement SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL (#23467) --- src/server/game/Entities/Unit/Unit.cpp | 80 ++++++++++++++----- .../game/Spells/Auras/SpellAuraDefines.h | 2 +- .../game/Spells/Auras/SpellAuraEffects.cpp | 2 +- 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index de78e18506..bdeea44c5a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2107,37 +2107,75 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr // attack can be redirected to another target victim = GetMeleeHitRedirectTarget(victim); - CalcDamageInfo damageInfo; - CalculateMeleeDamage(victim, 0, &damageInfo, attType); - // Send log damage message to client - DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb); - - // Sparring Checks - if (Creature* target = victim->ToCreature()) + AuraEffectList const& meleeAttackOverrides = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL); + AuraEffect const* meleeAttackAuraEffect = nullptr; + uint32 meleeAttackSpellId = 0; + if (attType == BASE_ATTACK) { - if (GetTypeId() == TYPEID_UNIT && !IsCharmedOwnedByPlayerOrPlayer()) + if (!meleeAttackOverrides.empty()) { - float sparringLimitPct = target->GetSparringHealthLimit(); + meleeAttackAuraEffect = meleeAttackOverrides.front(); + meleeAttackSpellId = meleeAttackAuraEffect->GetSpellInfo()->Effects[meleeAttackAuraEffect->GetEffIndex()].TriggerSpell; + } + } + else + { + auto itr = std::find_if(meleeAttackOverrides.begin(), meleeAttackOverrides.end(), [&](AuraEffect const* aurEff) + { + return aurEff->GetMiscValue() != 0; + }); - if (sparringLimitPct != 0.0f) - if (target->GetHealthPct() <= sparringLimitPct) - damageInfo.HitInfo |= HITINFO_FAKE_DAMAGE; + if (itr != meleeAttackOverrides.end()) + { + meleeAttackAuraEffect = *itr; + meleeAttackSpellId = meleeAttackAuraEffect->GetMiscValue(); } } - SendAttackStateUpdate(&damageInfo); + if (!meleeAttackAuraEffect) + { + CalcDamageInfo damageInfo; + CalculateMeleeDamage(victim, 0, &damageInfo, attType); + // Send log damage message to client + DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb); - DealMeleeDamage(&damageInfo, true); + // Sparring Checks + if (Creature* target = victim->ToCreature()) + { + if (GetTypeId() == TYPEID_UNIT && !IsCharmedOwnedByPlayerOrPlayer()) + { + float sparringLimitPct = target->GetSparringHealthLimit(); - DamageInfo dmgInfo(damageInfo); - ProcSkillsAndAuras(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, PROC_SPELL_TYPE_NONE, PROC_SPELL_PHASE_NONE, dmgInfo.GetHitMask(), nullptr, &dmgInfo, nullptr); + if (sparringLimitPct != 0.0f) + if (target->GetHealthPct() <= sparringLimitPct) + damageInfo.HitInfo |= HITINFO_FAKE_DAMAGE; + } + } - if (GetTypeId() == TYPEID_PLAYER) - TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", - GetGUID().GetCounter(), victim->GetGUID().GetCounter(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); + SendAttackStateUpdate(&damageInfo); + + DealMeleeDamage(&damageInfo, true); + + DamageInfo dmgInfo(damageInfo); + ProcSkillsAndAuras(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, PROC_SPELL_TYPE_NONE, PROC_SPELL_PHASE_NONE, dmgInfo.GetHitMask(), nullptr, &dmgInfo, nullptr); + + if (GetTypeId() == TYPEID_PLAYER) + TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", + GetGUID().GetCounter(), victim->GetGUID().GetCounter(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); + else + TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", + GetGUID().GetCounter(), victim->GetGUID().GetCounter(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); + } else - TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", - GetGUID().GetCounter(), victim->GetGUID().GetCounter(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); + { + CastSpell(victim, meleeAttackSpellId, true, nullptr, meleeAttackAuraEffect); + + uint32 hitInfo = HITINFO_AFFECTS_VICTIM | HITINFO_NO_ANIMATION; + if (attType == OFF_ATTACK) + hitInfo |= HITINFO_OFFHAND; + + SendAttackStateUpdate(hitInfo, victim, 0, GetMeleeDamageSchoolMask(), 0, 0, 0, VICTIMSTATE_HIT, 0); + } } } diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index a89db43e0e..9d24648f37 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -431,7 +431,7 @@ enum AuraType : uint32 SPELL_AURA_WORGEN_ALTERED_FORM = 358, SPELL_AURA_359 = 359, SPELL_AURA_PROC_TRIGGER_SPELL_COPY = 360, // Procs the same spell that caused this proc (Dragonwrath, Tarecgosa's Rest) - SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL = 361, // NYI + SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL = 361, SPELL_AURA_362 = 362, // Not used in 4.3.4 SPELL_AURA_MOD_NEXT_SPELL = 363, // Used by 101601 Throw Totem - causes the client to initialize spell cast with specified spell SPELL_AURA_364 = 364, // Not used in 4.3.4 diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 9577fe5f5b..34d4907036 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -424,7 +424,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //358 SPELL_AURA_358 &AuraEffect::HandleNULL, //359 SPELL_AURA_359 &AuraEffect::HandleNoImmediateEffect, //360 SPELL_AURA_PROC_TRIGGER_SPELL_COPY implemented in AuraEffect::HandleProc - &AuraEffect::HandleNULL, //361 SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL + &AuraEffect::HandleNoImmediateEffect, //361 SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL implemented in Unit::AttackerStateUpdate &AuraEffect::HandleUnused, //362 unused (4.3.4) &AuraEffect::HandleNULL, //363 SPELL_AURA_MOD_NEXT_SPELL &AuraEffect::HandleUnused, //364 unused (4.3.4)