Core/Unit: damage immune improvements (9f5df023b7 follow up)

- Handling checked in sniffs: Spell 63710 Void Barrier vs 49143 Frost Strike
  * Send spell miss immune only if spell consists of damage effects
- Checked with 348 Immolate:
  * No packets sent if damage immune, aura is applied normally

Also... who the fuck uses 0 to compare against pointers

(cherry picked from commit ca1c4525c7)

Core/Unit: fix build

Ctrl-S failure
(cherry picked from commit f3bdd705c0)
This commit is contained in:
ariel-
2016-11-16 02:39:15 +01:00
committed by joschiwald
parent 9d0dfeb425
commit 5bcf14cdb8
7 changed files with 94 additions and 38 deletions

View File

@@ -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

View File

@@ -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());

View File

@@ -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

View File

@@ -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();

View File

@@ -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); }

View File

@@ -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;

View File

@@ -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;