Skip to content

Instantly share code, notes, and snippets.

@robinsch
Created October 24, 2015 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robinsch/13218e5f672db9b09096 to your computer and use it in GitHub Desktop.
Save robinsch/13218e5f672db9b09096 to your computer and use it in GitHub Desktop.
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 9ced65b..12ee925 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -1784,97 +1784,125 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
// split damage auras - only when not damaging self
if (victim != this)
+ SplitDamage(victim, schoolMask, dmgInfo);
+
+ *resist = dmgInfo.GetResist();
+ *absorb = dmgInfo.GetAbsorb();
+}
+
+void Unit::SplitDamage(Unit* victim, SpellSchoolMask schoolMask, DamageInfo dmgInfo)
+{
+ // 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 vSplitDamageFlatCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
+ for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
{
- // 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 vSplitDamageFlatCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
- for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
- {
- // Check if aura was removed during iteration - we don't need to work on such auras
- if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
- continue;
- // check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
- continue;
+ // Check if aura was removed during iteration - we don't need to work on such auras
+ if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
+ continue;
+ // check damage school mask
+ if (!((*itr)->GetMiscValue() & schoolMask))
+ continue;
- // Damage can be splitted only if aura has an alive caster
- Unit* caster = (*itr)->GetCaster();
- if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
- continue;
+ // Damage can be splitted only if aura has an alive caster
+ Unit* caster = (*itr)->GetCaster();
+ if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
+ continue;
- int32 splitDamage = (*itr)->GetAmount();
+ int32 splitDamage = (*itr)->GetAmount();
- // absorb must be smaller than the damage itself
- splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
+ // absorb must be smaller than the damage itself
+ splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
- dmgInfo.AbsorbDamage(splitDamage);
+ dmgInfo.AbsorbDamage(splitDamage);
- // check if caster is immune to damage
- if (caster->IsImmunedToDamage(schoolMask))
- {
- victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
- continue;
- }
+ // check if caster is immune to damage
+ if (caster->IsImmunedToDamage(schoolMask))
+ {
+ victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
+ continue;
+ }
- uint32 splitted = splitDamage;
- uint32 splitted_absorb = 0;
- DealDamageMods(caster, splitted, &splitted_absorb);
+ uint32 splitted = splitDamage;
+ uint32 splitted_absorb = 0;
+ DealDamageMods(caster, splitted, &splitted_absorb);
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
+ SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
- CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
- }
+ CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+ DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
+ }
- // 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 vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
- for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && dmgInfo.GetDamage() > 0; ++itr)
- {
- // Check if aura was removed during iteration - we don't need to work on such auras
- AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
- if (!aurApp)
- continue;
+ // 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 vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
+ for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && dmgInfo.GetDamage() > 0; ++itr)
+ {
+ // Check if aura was removed during iteration - we don't need to work on such auras
+ AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
+ if (!aurApp)
+ continue;
- // check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
- continue;
+ // check damage school mask
+ if (!((*itr)->GetMiscValue() & schoolMask))
+ continue;
- // Damage can be splitted only if aura has an alive caster
- Unit* caster = (*itr)->GetCaster();
- if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
- continue;
+ // Damage can be splitted only if aura has an alive caster
+ Unit* caster = (*itr)->GetCaster();
+ if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
+ continue;
- uint32 splitDamage = CalculatePct(dmgInfo.GetDamage(), (*itr)->GetAmount());
+ uint32 splitDamage = CalculatePct(dmgInfo.GetDamage(), (*itr)->GetAmount());
- (*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, dmgInfo, splitDamage);
+ (*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, dmgInfo, splitDamage);
- // absorb must be smaller than the damage itself
- splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
+ // absorb must be smaller than the damage itself
+ splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
- dmgInfo.AbsorbDamage(splitDamage);
+ dmgInfo.AbsorbDamage(splitDamage);
- // check if caster is immune to damage
- if (caster->IsImmunedToDamage(schoolMask))
+ // check if caster is immune to damage
+ if (caster->IsImmunedToDamage(schoolMask))
+ {
+ victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
+ continue;
+ }
+
+ uint32 split_absorb = 0;
+ DealDamageMods(caster, splitDamage, &split_absorb);
+
+ SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, schoolMask, split_absorb, 0, false, 0, false);
+
+ CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+ DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
+ // break 'Fear' and similar auras
+ caster->ProcDamageAndSpellFor(true, this, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_NORMAL_HIT, BASE_ATTACK, (*itr)->GetSpellInfo(), splitDamage);
+ }
+
+ // special case for Roar of Sacrifice
+ if (Aura* aura = victim->GetAura(53179))
+ {
+ if (Unit* auraCaster = aura->GetCaster())
+ {
+ if (auraCaster->IsHunterPet())
{
- victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
- continue;
- }
+ if (!auraCaster || (auraCaster == victim) || !auraCaster->IsInWorld() || !auraCaster->IsAlive())
+ return;
- uint32 split_absorb = 0;
- DealDamageMods(caster, splitDamage, &split_absorb);
+ // check if caster is immune to damage
+ if (auraCaster->IsImmunedToDamage(schoolMask))
+ {
+ victim->SendSpellMiss(auraCaster, aura->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
+ return;
+ }
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, schoolMask, split_absorb, 0, false, 0, false);
+ uint32 transferDamage = CalculatePct(dmgInfo.GetDamage(), 20);
- CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
- // break 'Fear' and similar auras
- caster->ProcDamageAndSpellFor(true, this, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_NORMAL_HIT, BASE_ATTACK, (*itr)->GetSpellInfo(), splitDamage);
+ CleanDamage cleanDamage = CleanDamage(transferDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+ DealDamage(auraCaster, transferDamage, &cleanDamage, DIRECT_DAMAGE, schoolMask, aura->GetSpellInfo()->Id, false);
+ }
}
}
-
- *resist = dmgInfo.GetResist();
- *absorb = dmgInfo.GetAbsorb();
}
void Unit::CalcHealAbsorb(Unit* victim, SpellInfo const* healSpell, uint32 &healAmount, uint32 &absorb)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 39b1c34..bc6b951 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1972,6 +1972,8 @@ class Unit : public WorldObject
void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL);
void CalcHealAbsorb(Unit* victim, SpellInfo const* spellInfo, uint32& healAmount, uint32& absorb);
+ void SplitDamage(Unit* victim, SpellSchoolMask schoolMask, DamageInfo dmgInfo);
+
void UpdateSpeed(UnitMoveType mtype, bool forced);
float GetSpeed(UnitMoveType mtype) const;
float GetSpeedRate(UnitMoveType mtype) const { return m_speed_rate[mtype]; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment