mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
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 commitca1c4525c7) Core/Unit: fix build Ctrl-S failure (cherry picked from commitf3bdd705c0)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user