aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp45
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp6
-rw-r--r--src/server/game/Spells/Spell.cpp35
-rw-r--r--src/server/game/Spells/SpellInfo.cpp29
-rw-r--r--src/server/game/Spells/SpellInfo.h1
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp10
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp6
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;