diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 45 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 35 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 29 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 1 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_misc.cpp | 10 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp | 6 |
7 files changed, 94 insertions, 38 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 77d71e21f00..c16c0f7d295 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -703,12 +703,6 @@ void Unit::DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) co uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss) { - if (victim->IsImmunedToDamage(spellProto)) - { - SendSpellDamageImmune(victim, spellProto->Id, false); - return 0; - } - if (victim->IsAIEnabled) victim->GetAI()->DamageTaken(this, damage); @@ -1186,7 +1180,6 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage const* damageInfo, bool durabilit return; Unit* victim = damageInfo->target; - if (!victim) return; @@ -1471,47 +1464,48 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) // We're going to call functions which can modify content of the list during iteration over it's elements // Let's copy the list so we can prevent iterator invalidation AuraEffectList vDamageShieldsCopy(victim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD)); - for (AuraEffectList::const_iterator dmgShieldItr = vDamageShieldsCopy.begin(); dmgShieldItr != vDamageShieldsCopy.end(); ++dmgShieldItr) + for (AuraEffect const* aurEff : vDamageShieldsCopy) { - SpellInfo const* i_spellProto = (*dmgShieldItr)->GetSpellInfo(); + SpellInfo const* spellInfo = aurEff->GetSpellInfo(); + // Damage shield can be resisted... - if (SpellMissInfo missInfo = victim->SpellHitResult(this, i_spellProto, false)) + SpellMissInfo missInfo = victim->SpellHitResult(this, spellInfo, false); + if (missInfo != SPELL_MISS_NONE) { - victim->SendSpellMiss(this, i_spellProto->Id, missInfo); + victim->SendSpellMiss(this, spellInfo->Id, missInfo); continue; } // ...or immuned - if (IsImmunedToDamage(i_spellProto)) + if (IsImmunedToDamage(spellInfo)) { - victim->SendSpellDamageImmune(this, i_spellProto->Id, false); + victim->SendSpellDamageImmune(this, spellInfo->Id, false); continue; } - uint32 damage = (*dmgShieldItr)->GetAmount(); - - if (Unit* caster = (*dmgShieldItr)->GetCaster()) + uint32 damage = aurEff->GetAmount(); + if (Unit* caster = aurEff->GetCaster()) { - damage = caster->SpellDamageBonusDone(this, i_spellProto, damage, SPELL_DIRECT_DAMAGE, (*dmgShieldItr)->GetSpellEffectInfo()); - damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE, (*dmgShieldItr)->GetSpellEffectInfo()); + damage = caster->SpellDamageBonusDone(this, spellInfo, damage, SPELL_DIRECT_DAMAGE, aurEff->GetSpellEffectInfo()); + damage = this->SpellDamageBonusTaken(caster, spellInfo, damage, SPELL_DIRECT_DAMAGE, aurEff->GetSpellEffectInfo()); } - DamageInfo damageInfo(this, victim, damage, i_spellProto, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK); + DamageInfo damageInfo(this, victim, damage, spellInfo, spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK); victim->CalcAbsorbResist(damageInfo); damage = damageInfo.GetDamage(); // No Unit::CalcAbsorbResist here - opcode doesn't send that data - this damage is probably not affected by that - victim->DealDamageMods(this, damage, NULL); + victim->DealDamageMods(this, damage, nullptr); WorldPackets::CombatLog::SpellDamageShield damageShield; damageShield.Attacker = victim->GetGUID(); damageShield.Defender = GetGUID(); - damageShield.SpellID = i_spellProto->Id; + damageShield.SpellID = spellInfo->Id; damageShield.TotalDamage = damage; damageShield.OverKill = std::max(int32(damage) - int32(GetHealth()), 0); - damageShield.SchoolMask = i_spellProto->SchoolMask; + damageShield.SchoolMask = spellInfo->SchoolMask; damageShield.LogAbsorbed = damageInfo.GetAbsorb(); - victim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true); + victim->DealDamage(this, damage, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true); damageShield.LogData.Initialize(this); victim->SendCombatLogMessage(&damageShield); @@ -2530,6 +2524,11 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, boo if (victim->IsImmunedToSpell(spellInfo)) return SPELL_MISS_IMMUNE; + // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply + // returns SPELL_MISS_IMMUNE in that case, for other spells, the SMSG_SPELL_GO must show hit + if (spellInfo->HasOnlyDamageEffects() && victim->IsImmunedToDamage(spellInfo)) + return SPELL_MISS_IMMUNE; + // All positive spells can`t miss /// @todo client not show miss log for this spells - so need find info for this in dbc and use it! if (spellInfo->IsPositive() && !IsHostileTo(victim)) // prevent from affecting enemy by "positive" spell diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index ab73f37f8ea..34117fee742 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -6001,6 +6001,12 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv { Unit* target = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); + if (triggerTarget->HasUnitState(UNIT_STATE_ISOLATED) || triggerTarget->IsImmunedToDamage(GetSpellInfo())) + { + SendTickImmune(triggerTarget, target); + return; + } + SpellNonMeleeDamage damageInfo(target, triggerTarget, GetId(), GetBase()->GetSpellXSpellVisualId(), GetSpellInfo()->SchoolMask, GetBase()->GetCastGUID()); uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE, GetSpellEffectInfo()); damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE, GetSpellEffectInfo()); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f683d0fe1cd..a98a65cfd16 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2510,12 +2510,30 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Fill base damage struct (unitTarget - is real spell target) SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_SpellVisual, m_spellSchoolMask, m_castId); - // Add bonuses and fill damageInfo struct - caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit); - caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); + // Check damage immunity + if (unitTarget->IsImmunedToDamage(m_spellInfo)) + { + hitMask = PROC_HIT_IMMUNE; + m_damage = 0; - hitMask |= createProcHitMask(&damageInfo, missInfo); - procVictim |= PROC_FLAG_TAKEN_DAMAGE; + // no packet found in sniffs + } + else + { + // Add bonuses and fill damageInfo struct + caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit); + caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); + + hitMask |= createProcHitMask(&damageInfo, missInfo); + procVictim |= PROC_FLAG_TAKEN_DAMAGE; + + m_damage = damageInfo.damage; + + caster->DealSpellDamage(&damageInfo, true); + + // Send log damage message to client + caster->SendSpellNonMeleeDamageLog(&damageInfo); + } // Do triggers for unit if (canEffectTrigger) @@ -2527,13 +2545,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)) caster->ToPlayer()->CastItemCombatSpell(spellDamageInfo); } - - m_damage = damageInfo.damage; - - caster->DealSpellDamage(&damageInfo, true); - - // Send log damage message to client - caster->SendSpellNonMeleeDamageLog(&damageInfo); } // Passive spell hits/misses or active spells only misses (only triggers) else diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index cc85cbabadc..7acc30befa7 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1239,6 +1239,35 @@ bool SpellInfo::HasAreaAuraEffect() const return false; } +bool SpellInfo::HasOnlyDamageEffects() const +{ + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (!effect) + continue; + + switch (effect->Effect) + { + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT: + continue; + default: + return false; + } + } + } + + return true; +} + bool SpellInfo::HasAnyAuraInterruptFlag() const { return std::find_if(AuraInterruptFlags.begin(), AuraInterruptFlags.end(), [](uint32 flag) { return flag != 0; }) != AuraInterruptFlags.end(); diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index db53572abe8..6af4ea95ba7 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -527,6 +527,7 @@ class TC_GAME_API SpellInfo bool HasAura(uint32 difficulty, AuraType aura) const; bool HasAreaAuraEffect(uint32 difficulty) const; bool HasAreaAuraEffect() const; + bool HasOnlyDamageEffects() const; bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); } bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 6d44db6cd3b..a046b487165 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2421,10 +2421,11 @@ public: char* spellStr = strtok((char*)NULL, " "); + Player* attacker = handler->GetSession()->GetPlayer(); + // melee damage by specific school if (!spellStr) { - Player* attacker = handler->GetSession()->GetPlayer(); DamageInfo dmgInfo(attacker, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK); attacker->CalcAbsorbResist(dmgInfo); @@ -2445,13 +2446,16 @@ public: // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellid = handler->extractSpellIdFromLink((char*)args); + if (!spellid) + return false; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) return false; - SpellNonMeleeDamage damageInfo(handler->GetSession()->GetPlayer(), target, spellid, spellInfo->GetSpellXSpellVisualId(handler->GetSession()->GetPlayer()), spellInfo->SchoolMask); + SpellNonMeleeDamage damageInfo(attacker, target, spellid, spellInfo->GetSpellXSpellVisualId(handler->GetSession()->GetPlayer()), spellInfo->SchoolMask); damageInfo.damage = damage; - handler->GetSession()->GetPlayer()->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); + attacker->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); target->DealSpellDamage(&damageInfo, true); target->SendSpellNonMeleeDamageLog(&damageInfo); return true; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index f9af80eaca1..da5359364ff 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -1103,6 +1103,12 @@ class spell_sindragosa_s_fury : public SpellScriptLoader if (!GetHitUnit()->IsAlive() || !_targetCount) return; + if (GetHitUnit()->IsImmunedToDamage(GetSpellInfo())) + { + GetCaster()->SendSpellDamageImmune(GetHitUnit(), GetSpellInfo()->Id, false); + return; + } + float resistance = float(GetHitUnit()->GetResistance(SpellSchoolMask(GetSpellInfo()->SchoolMask))); uint32 minResistFactor = uint32((resistance / (resistance + 510.0f)) * 10.0f) * 2; uint32 randomResist = urand(0, (9 - minResistFactor) * 100) / 100 + minResistFactor; |