aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/world_database.sql16
-rw-r--r--sql/updates/10885_world_spell_script_names.sql27
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp250
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp15
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.h1
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp4
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h7
-rw-r--r--src/server/scripts/Examples/example_spell.cpp14
-rw-r--r--src/server/scripts/Outland/BlackTemple/illidari_council.cpp33
-rw-r--r--src/server/scripts/PrecompiledHeaders/ScriptPCH.h1
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp239
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp29
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp36
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp95
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp77
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp110
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp79
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp8
18 files changed, 753 insertions, 288 deletions
diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql
index afe2a8e2486..33d8b043793 100644
--- a/sql/base/world_database.sql
+++ b/sql/base/world_database.sql
@@ -26735,6 +26735,8 @@ LOCK TABLES `spell_script_names` WRITE;
/*!40000 ALTER TABLE `spell_script_names` DISABLE KEYS */;
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
-- generic
+( 39228, 'spell_gen_absorb0_hitlimit1'),
+( 60218, 'spell_gen_absorb0_hitlimit1'),
( 6962, 'spell_gen_pet_summoned'),
( 10848, 'spell_gen_shroud_of_death'),
( 24750, 'spell_gen_trick'),
@@ -26755,6 +26757,8 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
( 72757, 'spell_pvp_trinket_wotf_shared_cd'),
( 46221, 'spell_gen_animal_blood'),
-- instances
+-- Black Temple
+( 41475, 'spell_boss_lady_malande_shield'),
-- Forge of Souls
( 68793, 'spell_bronjahm_magic_bane'),
( 69050, 'spell_bronjahm_magic_bane'),
@@ -26912,6 +26916,7 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
-- warrior
( 12975, 'spell_warr_last_stand'),
-- paladin
+(-31850, 'spell_pal_ardent_defender'),
( 20425, 'spell_pal_judgement_of_command'),
( 63521, 'spell_pal_guarded_by_the_light'),
(-20473, 'spell_pal_holy_shock'),
@@ -26929,19 +26934,26 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
( 55709, 'spell_hun_pet_heart_of_the_phoenix'),
( 54044, 'spell_hun_pet_carrion_feeder'),
-- rogue
+(-31228, 'spell_rog_cheat_death'),
(-31130, 'spell_rog_nerves_of_steel'),
( 5938, 'spell_rog_shiv'),
( 14185, 'spell_rog_preparation'),
(-51685, 'spell_rog_prey_on_the_weak'),
-- priest
+(-47788, 'spell_pri_guardian_spirit'),
+( -8129, 'spell_pri_mana_burn'),
( 47948, 'spell_pri_pain_and_suffering_proc'),
(-47540, 'spell_pri_penance'),
-( -8129, 'spell_pri_mana_burn'),
+( -17, 'spell_pri_reflective_shield_trigger'),
-- death knight
+( 50462, 'spell_dk_anti_magic_shell_raid'),
+( 48707, 'spell_dk_anti_magic_shell_self'),
+( 50461, 'spell_dk_anti_magic_zone'),
(-49158, 'spell_dk_corpse_explosion'),
( 50524, 'spell_dk_runic_power_feed'),
(-55090, 'spell_dk_scourge_strike'),
(-49145, 'spell_dk_spell_deflection'),
+(-52284, 'spell_dk_will_of_the_necropolis'),
-- shaman
(-51474, 'spell_sha_astral_shift'),
( 39610, 'spell_sha_mana_tide_totem'),
@@ -26950,6 +26962,8 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
-- mage
(-11113, 'spell_mage_blast_wave'),
( 11958, 'spell_mage_cold_snap'),
+( -543, 'spell_mage_frost_warding_trigger'),
+( -6143, 'spell_mage_frost_warding_trigger'),
( 31687, 'spell_mage_summon_water_elemental'),
( 32826, 'spell_mage_polymorph_visual'),
-- warlock
diff --git a/sql/updates/10885_world_spell_script_names.sql b/sql/updates/10885_world_spell_script_names.sql
new file mode 100644
index 00000000000..2dc9a2f4f2b
--- /dev/null
+++ b/sql/updates/10885_world_spell_script_names.sql
@@ -0,0 +1,27 @@
+DELETE FROM `spell_script_names` WHERE `spell_id`=41475 AND `ScriptName`='spell_boss_lady_malande_shield';
+DELETE FROM `spell_script_names` WHERE `spell_id`=-31850 AND `ScriptName`='spell_pal_ardent_defender';
+DELETE FROM `spell_script_names` WHERE `spell_id`=50462 AND `ScriptName`='spell_dk_anti_magic_shell_raid';
+DELETE FROM `spell_script_names` WHERE `spell_id`=48707 AND `ScriptName`='spell_dk_anti_magic_shell_self';
+DELETE FROM `spell_script_names` WHERE `spell_id`=50461 AND `ScriptName`='spell_dk_anti_magic_zone';
+DELETE FROM `spell_script_names` WHERE `spell_id`=-52284 AND `ScriptName`='spell_dk_will_of_the_necropolis';
+DELETE FROM `spell_script_names` WHERE `spell_id`=39228 AND `ScriptName`='spell_gen_absorb0_hitlimit1';
+DELETE FROM `spell_script_names` WHERE `spell_id`=60218 AND `ScriptName`='spell_gen_absorb0_hitlimit1';
+DELETE FROM `spell_script_names` WHERE `spell_id`=-543 AND `ScriptName`='spell_mage_frost_warding_trigger';
+DELETE FROM `spell_script_names` WHERE `spell_id`=-6143 AND `ScriptName`='spell_mage_frost_warding_trigger';
+DELETE FROM `spell_script_names` WHERE `spell_id`=-17 AND `ScriptName`='spell_pri_reflective_shield_trigger';
+DELETE FROM `spell_script_names` WHERE `spell_id`=-47788 AND `ScriptName`='spell_pri_guardian_spirit';
+DELETE FROM `spell_script_names` WHERE `spell_id`=-31228 AND `ScriptName`='spell_rog_cheat_death';
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+( 41475, 'spell_boss_lady_malande_shield'),
+(-31850, 'spell_pal_ardent_defender'),
+( 50462, 'spell_dk_anti_magic_shell_raid'),
+( 48707, 'spell_dk_anti_magic_shell_self'),
+( 50461, 'spell_dk_anti_magic_zone'),
+(-52284, 'spell_dk_will_of_the_necropolis'),
+( 39228, 'spell_gen_absorb0_hitlimit1'),
+( 60218, 'spell_gen_absorb0_hitlimit1'),
+( -543, 'spell_mage_frost_warding_trigger'),
+( -6143, 'spell_mage_frost_warding_trigger'),
+( -17, 'spell_pri_reflective_shield_trigger'),
+(-47788, 'spell_pri_guardian_spirit'),
+(-31228, 'spell_rog_cheat_death');
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 69bec5d20ea..dcaea3186cc 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -1614,10 +1614,6 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
dmgInfo.ResistDamage(damageResisted);
}
- // Death Prevention Aura
- SpellEntry const* preventDeathSpell = NULL;
- int32 preventDeathAmount = 0;
-
// Incanter's Absorption, for converting to spell power
int32 incanterAbsorption = 0;
@@ -1673,208 +1669,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
bool defaultPrevented = false;
absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, absorb, defaultPrevented);
-
currentAbsorb = absorb;
- switch (spellProto->SpellFamilyName)
- {
- case SPELLFAMILY_GENERIC:
- {
- // Reflective Shield (Lady Malande boss)
- if (spellProto->Id == 41475)
- {
- int32 bp = std::min(int32(dmgInfo.GetDamage()), currentAbsorb) / 2;
- pVictim->CastCustomSpell(this, 33619, &bp, NULL, NULL, true, NULL, *itr);
- break;
- }
- if ((spellProto->Id == 39228) || // Argussian Compass
- (spellProto->Id == 60218)) // Essence of Gossamer
- {
- // Max absorb stored in 1 dummy effect
- int32 maxAbsorb = SpellMgr::CalculateSpellEffectAmount(spellProto, EFFECT_1);
- if (maxAbsorb < currentAbsorb)
- currentAbsorb = maxAbsorb;
- break;
- }
- break;
- }
- case SPELLFAMILY_MAGE:
- {
- // possibly create BeforeEffectAbsorb for this?
- // Frost ward and Fire Ward
- if (spellProto->Category == 56)
- {
- // Frost Warding
- if (AuraEffect * aurEff = pVictim->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_MAGE, 501, EFFECT_0))
- {
- int32 chance = SpellMgr::CalculateSpellEffectAmount(aurEff->GetSpellProto(), EFFECT_1);
-
- if (roll_chance_i(chance))
- {
- int32 bp = dmgInfo.GetDamage();
- pVictim->CastCustomSpell(pVictim, 57776, &bp, NULL, NULL, true, NULL, absorbAurEff);
- dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
- continue;
- }
- }
- }
- break;
- }
- case SPELLFAMILY_ROGUE:
- {
- // Cheat Death (make less prio with Guardian Spirit case)
- if (spellProto->SpellIconID == 2109)
- {
- if (!preventDeathSpell && pVictim->ToPlayer())
- if (!pVictim->ToPlayer()->HasSpellCooldown(31231) && roll_chance_i(absorbAurEff->GetAmount()))
- preventDeathSpell = absorbAurEff->GetSpellProto();
- continue;
- }
- break;
- }
- case SPELLFAMILY_PRIEST:
- {
- // Guardian Spirit
- if (spellProto->SpellIconID == 2873)
- {
- preventDeathSpell = absorbAurEff->GetSpellProto();
- preventDeathAmount = absorbAurEff->GetAmount();
- continue;
- }
- // Power Word: Shield
- if (spellProto->SpellFamilyFlags.IsEqual(0x1, 0, 0x400))
- {
- if (pVictim == this)
- break;
-
- Unit * caster = absorbAurEff->GetCaster();
- if (!caster)
- break;
-
- // Reflective Shield
- if (AuraEffect const * aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 566, EFFECT_0))
- switch(aurEff->GetMiscValue())
- {
- case 5065: // Rank 1
- case 5064: // Rank 2
- {
- int32 bp = CalculatePctN(std::min(int32(dmgInfo.GetDamage()), currentAbsorb), aurEff->GetAmount());
- pVictim->CastCustomSpell(this, 33619, &bp, NULL, NULL, true, NULL, *itr);
- break;
- }
- default:
- sLog->outError("Unit::CalcAbsorbResist: unknown Reflective Shield spell %d", aurEff->GetId());
- break;
- }
- }
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- // Ardent Defender
- if (spellProto->SpellIconID == 2135)
- {
- if (!pVictim->ToPlayer())
- continue;
-
- int32 remainingHealth = pVictim->GetHealth() - dmgInfo.GetDamage();
- uint32 allowedHealth = pVictim->CountPctFromMaxHealth(35);
- // If damage kills us
- if (remainingHealth <= 0 && !pVictim->ToPlayer()->HasSpellCooldown(66235))
- {
- // Cast healing spell, completely avoid damage
- dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
-
- uint32 defenseSkillValue = pVictim->GetDefenseSkillValue();
- // Max heal when defense skill denies critical hits from raid bosses
- // Formula: max defense at level + 140 (raiting from gear)
- uint32 reqDefForMaxHeal = pVictim->getLevel() * 5 + 140;
- float pctFromDefense = (defenseSkillValue >= reqDefForMaxHeal)
- ? 1.0f
- : float(defenseSkillValue) / float(reqDefForMaxHeal);
-
- int32 healAmount = int32(pVictim->CountPctFromMaxHealth(uint32(absorbAurEff->GetAmount() * pctFromDefense)));
- pVictim->CastCustomSpell(pVictim, 66235, &healAmount, NULL, NULL, true, NULL, *itr);
- pVictim->ToPlayer()->AddSpellCooldown(66235, 0, time(NULL) + 120);
- }
- else if (remainingHealth < int32(allowedHealth))
- {
- // Reduce damage that brings us under 35% (or full damage if we are already under 35%) by x%
- uint32 damageToReduce = (pVictim->GetHealth() < allowedHealth)
- ? dmgInfo.GetDamage()
- : allowedHealth - remainingHealth;
- dmgInfo.AbsorbDamage(CalculatePctN(damageToReduce, currentAbsorb));
- }
- continue;
- }
- break;
- }
- case SPELLFAMILY_DEATHKNIGHT:
- {
- switch (spellProto->Id)
- {
- case 51271: // Unbreakable Armor
- if (Unit * caster = absorbAurEff->GetCaster())
- {
- uint32 absorbed = uint32(currentAbsorb * caster->GetArmor() * 0.01f);
-
- // Glyph of Unbreakable Armor
- if (AuraEffect const * aurEff = caster->GetAuraEffect(58635, 0))
- AddPctN(absorbed, aurEff->GetAmount());
-
- dmgInfo.AbsorbDamage(absorbed);
- }
- continue;
- case 52284: // Will of the Necropolis
- case 52285:
- case 52286:
- {
- int32 remainingHp = int32(pVictim->GetHealth() - dmgInfo.GetDamage());
-
- // min pct of hp is stored in effect 0 of talent spell
- uint32 rank = sSpellMgr->GetSpellRank(spellProto->Id);
- SpellEntry const * talentProto = sSpellStore.LookupEntry(sSpellMgr->GetSpellWithRank(49189, rank));
-
- int32 minHp = int32(pVictim->CountPctFromMaxHealth(SpellMgr::CalculateSpellEffectAmount(talentProto, EFFECT_0, absorbAurEff->GetCaster())));
- // Damage that would take you below [effect0] health or taken while you are at [effect0]
- if (remainingHp < minHp)
- {
- uint32 absorbed = uint32(currentAbsorb * dmgInfo.GetDamage() * 0.01f);
- dmgInfo.AbsorbDamage(absorbed);
- }
- continue;
- }
- case 48707: // Anti-Magic Shell (on self)
- {
- // damage absorbed by Anti-Magic Shell energizes the DK with additional runic power.
- // This, if I'm not mistaken, shows that we get back ~2% of the absorbed damage as runic power.
- int32 absorbed = CalculatePctN(dmgInfo.GetDamage(), currentAbsorb);
- dmgInfo.AbsorbDamage(absorbed);
- int32 bp = absorbed * 2 / 10;
- pVictim->CastCustomSpell(pVictim, 49088, &bp, NULL, NULL, true, NULL, *itr);
- continue;
- }
- case 50462: // Anti-Magic Shell (on single party/raid member)
- dmgInfo.AbsorbDamage(CalculatePctN(dmgInfo.GetDamage(), currentAbsorb));
- continue;
- case 50461: // Anti-Magic Zone
- if (Unit * caster = absorbAurEff->GetCaster())
- {
- int32 absorbed = CalculatePctN(dmgInfo.GetDamage(), currentAbsorb);
- int32 canabsorb = caster->GetHealth();
- if (canabsorb < absorbed)
- absorbed = canabsorb;
-
- dmgInfo.AbsorbDamage(absorbed);
- }
- continue;
- default:
- break;
- }
- break;
- }
- default:
- break;
- }
if (defaultPrevented)
continue;
@@ -1892,6 +1687,9 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
if (spellProto->SpellFamilyName == SPELLFAMILY_MAGE && spellProto->SpellFamilyFlags[2] & 0x8)
incanterAbsorption += currentAbsorb;
+ absorb = currentAbsorb;
+ absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, absorb);
+
// Check if our aura is using amount to count damage
if (absorbAurEff->GetAmount() >= 0)
{
@@ -1950,7 +1748,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
}
// split damage auras - only when not damaging self
- if (pVictim != this)
+ if (pVictim != this)
{
// 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
@@ -2021,46 +1819,6 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
}
}
- // Apply death prevention spells effects
- if (auraAbsorbMod < 100) // Do nothing if 100% absorb ignore
- if (preventDeathSpell && (dmgInfo.GetDamage() >= int32(pVictim->GetHealth())))
- {
- switch(preventDeathSpell->SpellFamilyName)
- {
- case SPELLFAMILY_ROGUE:
- {
- // Cheat Death
- if (preventDeathSpell->SpellIconID == 2109)
- {
- pVictim->CastSpell(pVictim, 31231, true);
- pVictim->ToPlayer()->AddSpellCooldown(31231, 0, time(NULL) + 60);
-
- uint32 health10 = pVictim->CountPctFromMaxHealth(10);
-
- // hp > 10% - absorb hp till 10%
- if (pVictim->GetHealth() > health10)
- dmgInfo.AbsorbDamage(dmgInfo.GetDamage() - pVictim->GetHealth() + health10);
- // hp lower than 10% - absorb everything
- else
- dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
- }
- break;
- }
- case SPELLFAMILY_PRIEST:
- {
- // Guardian Spirit
- if (preventDeathSpell->SpellIconID == 2873)
- {
- int32 healAmount = int32(pVictim->CountPctFromMaxHealth(preventDeathAmount));
- pVictim->RemoveAurasDueToSpell(preventDeathSpell->Id);
- pVictim->CastCustomSpell(pVictim, 48153, &healAmount, NULL, NULL, true);
- dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
- }
- break;
- }
- }
- }
-
*resist = dmgInfo.GetResist();
*absorb = dmgInfo.GetAbsorb();
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 5068de484af..4642b15c724 100755
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1785,6 +1785,21 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect * aurEff, AuraApplication c
}
}
+void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect * aurEff, AuraApplication const * aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount)
+{
+ for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
+ std::list<AuraScript::EffectAbsorbHandler>::iterator effEndItr = (*scritr)->AfterEffectAbsorb.end(), effItr = (*scritr)->AfterEffectAbsorb.begin();
+ for(; effItr != effEndItr ; ++effItr)
+ {
+ if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
+ (*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount);
+ }
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
UnitAura::UnitAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID)
: Aura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID)
{
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index ab9a56be7fc..366373f6b53 100755
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -175,6 +175,7 @@ class Aura
void CallScriptEffectCalcPeriodicHandlers(AuraEffect const * aurEff, bool & isPeriodic, int32 & amplitude);
void CallScriptEffectCalcSpellModHandlers(AuraEffect const * aurEff, SpellModifier *& spellMod);
void CallScriptEffectAbsorbHandlers(AuraEffect * aurEff, AuraApplication const * aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented);
+ void CallScriptEffectAfterAbsorbHandlers(AuraEffect * aurEff, AuraApplication const * aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
std::list<AuraScript *> m_loadedScripts;
private:
void _DeleteRemovedApplications();
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 482a185f590..e175e9d688e 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -447,6 +447,10 @@ bool AuraScript::_Validate(SpellEntry const * entry)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+ for (std::list<EffectAbsorbHandler>::iterator itr = AfterEffectAbsorb.begin(); itr != AfterEffectAbsorb.end(); ++itr)
+ if (!(*itr).GetAffectedEffectsMask(entry))
+ sLog->outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+
return _SpellScript::_Validate(entry);
}
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 2d5d81e6310..ad231d757f5 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -283,6 +283,7 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC,
AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD,
AURA_SCRIPT_HOOK_EFFECT_ABSORB,
+ AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB,
/*AURA_SCRIPT_HOOK_APPLY,
AURA_SCRIPT_HOOK_REMOVE,*/
};
@@ -447,6 +448,12 @@ class AuraScript : public _SpellScript
HookList<EffectAbsorbHandler> OnEffectAbsorb;
#define AuraEffectAbsorbFn(F, I) EffectAbsorbFunction(&F, I)
+ // executed after absorb aura effect to reduced damage to target - absorbAmount is real amount absorbed by aura
+ // example: OnEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
+ // where function is: void function (AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount);
+ HookList<EffectAbsorbHandler> AfterEffectAbsorb;
+ #define AuraEffectAbsorbFn(F, I) EffectAbsorbFunction(&F, I)
+
// executed after aura absorbtions reduced damage
// example: AfterAbsorb += AuraAbsorbFn(class::function);
// where function is: void function (AuraEffect * aurEff, DamageInfo & dmgInfo);
diff --git a/src/server/scripts/Examples/example_spell.cpp b/src/server/scripts/Examples/example_spell.cpp
index 8d44cb92a4d..2a9d9a605c4 100644
--- a/src/server/scripts/Examples/example_spell.cpp
+++ b/src/server/scripts/Examples/example_spell.cpp
@@ -285,14 +285,6 @@ class spell_ex_absorb_aura : public SpellScriptLoader
SPELL_TRIGGERED = 18282
};
- bool Validate(SpellEntry const * /*spellEntry*/)
- {
- // check if spellid exists in dbc, we will trigger it later
- if (!sSpellStore.LookupEntry(SPELL_TRIGGERED))
- return false;
- return true;
- }
-
void HandleOnEffectAbsorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
{
sLog->outString("Our aura is now absorbing damage done to us!");
@@ -300,6 +292,11 @@ class spell_ex_absorb_aura : public SpellScriptLoader
absorbAmount = dmgInfo.GetDamage();
}
+ void HandleAfterEffectAbsorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ sLog->outString("Our aura has absorbed %u damage!", absorbAmount);
+ }
+
/*void HandleAfterAbsorb(DamageInfo & dmgInfo)
{
sLog->outString("Our auras have just absorbed damage done to us!");
@@ -309,6 +306,7 @@ class spell_ex_absorb_aura : public SpellScriptLoader
void Register()
{
OnEffectAbsorb += AuraEffectAbsorbFn(spell_ex_absorb_auraAuraScript::HandleOnEffectAbsorb, EFFECT_0);
+ AfterEffectAbsorb += AuraEffectAbsorbFn(spell_ex_absorb_auraAuraScript::HandleAfterEffectAbsorb, EFFECT_0);
//AfterAbsorb += AuraAbsorbFn(spell_ex_absorb_auraAuraScript::HandleAfterAbsorb);
}
};
diff --git a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp
index efcc8285984..9dc832d3056 100644
--- a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp
+++ b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp
@@ -89,6 +89,7 @@ static CouncilYells CouncilEnrage[]=
#define SPELL_EMPOWERED_SMITE 41471
#define SPELL_CIRCLE_OF_HEALING 41455
#define SPELL_REFLECTIVE_SHIELD 41475
+#define SPELL_REFLECTIVE_SHIELD_T 33619
#define SPELL_DIVINE_WRATH 41472
#define SPELL_HEAL_VISUAL 24171
@@ -878,14 +879,43 @@ public:
}
}
};
-
};
+// SPELL_REFLECTIVE_SHIELD
+class spell_boss_lady_malande_shield : public SpellScriptLoader
+{
+public:
+ spell_boss_lady_malande_shield() : SpellScriptLoader("spell_boss_lady_malande_shield") { }
+ class spell_boss_lady_malande_shield_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_boss_lady_malande_shield_AuraScript);
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ return sSpellStore.LookupEntry(SPELL_REFLECTIVE_SHIELD_T);
+ }
+ void Trigger(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit * target = GetTarget();
+ if (dmgInfo.GetAttacker() == target)
+ return;
+ int32 bp = absorbAmount / 2;
+ target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_REFLECTIVE_SHIELD_T, &bp, NULL, NULL, true, NULL, aurEff);
+ }
+ void Register()
+ {
+ AfterEffectAbsorb += AuraEffectAbsorbFn(spell_boss_lady_malande_shield_AuraScript::Trigger, EFFECT_0);
+ }
+ };
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_boss_lady_malande_shield_AuraScript();
+ }
+};
void AddSC_boss_illidari_council()
{
@@ -895,4 +925,5 @@ void AddSC_boss_illidari_council()
new boss_lady_malande();
new boss_veras_darkshadow();
new boss_high_nethermancer_zerevor();
+ new spell_boss_lady_malande_shield();
}
diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h b/src/server/scripts/PrecompiledHeaders/ScriptPCH.h
index 2cba3171202..1cd25309055 100644
--- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h
+++ b/src/server/scripts/PrecompiledHeaders/ScriptPCH.h
@@ -23,6 +23,7 @@
#include "DBCStores.h"
#include "ObjectMgr.h"
#include "SpellScript.h"
+#include "SpellAuraEffects.h"
#ifdef _WIN32
#include <windows.h>
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index 706853db0ae..35656dd9af4 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -32,6 +32,165 @@ enum DeathKnightSpells
DK_SPELL_SCOURGE_STRIKE_TRIGGERED = 70890,
};
+// 50462 - Anti-Magic Shell (on raid member)
+class spell_dk_anti_magic_shell_raid : public SpellScriptLoader
+{
+public:
+ spell_dk_anti_magic_shell_raid() : SpellScriptLoader("spell_dk_anti_magic_shell_raid") { }
+
+ class spell_dk_anti_magic_shell_raid_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_dk_anti_magic_shell_raid_AuraScript);
+
+ uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
+ void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
+ {
+ // TODO: this should absorb limited amount of damage, but no info on calculation formula
+ amount = -1;
+ }
+
+ void Absorb(AuraEffect * /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ absorbAmount = CalculatePctN(dmgInfo.GetDamage(), absorbPct);
+ }
+
+ void Register()
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_anti_magic_shell_raid_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_dk_anti_magic_shell_raid_AuraScript::Absorb, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_dk_anti_magic_shell_raid_AuraScript();
+ }
+};
+
+// 48707 - Anti-Magic Shell (on self)
+class spell_dk_anti_magic_shell_self : public SpellScriptLoader
+{
+public:
+ spell_dk_anti_magic_shell_self() : SpellScriptLoader("spell_dk_anti_magic_shell_self") { }
+
+ class spell_dk_anti_magic_shell_self_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_dk_anti_magic_shell_self_AuraScript);
+
+ enum Spells
+ {
+ DK_SPELL_RUNIC_POWER_ENERGIZE = 49088,
+ };
+
+ uint32 absorbPct, hpPct;
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ hpPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_1, GetCaster());
+ return true;
+ }
+
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ return sSpellStore.LookupEntry(DK_SPELL_RUNIC_POWER_ENERGIZE);
+ }
+
+ void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
+ {
+ // Set absorbtion amount to unlimited
+ amount = -1;
+ }
+
+ void Absorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ absorbAmount = std::min(CalculatePctN(dmgInfo.GetDamage(), absorbPct), GetTarget()->CountPctFromMaxHealth(hpPct));
+ }
+
+ void Trigger(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit * target = GetTarget();
+ // damage absorbed by Anti-Magic Shell energizes the DK with additional runic power.
+ // This, if I'm not mistaken, shows that we get back ~20% of the absorbed damage as runic power.
+ int32 bp = absorbAmount * 2 / 10;
+ target->CastCustomSpell(target, DK_SPELL_RUNIC_POWER_ENERGIZE, &bp, NULL, NULL, true, NULL, aurEff);
+ }
+
+ void Register()
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_anti_magic_shell_self_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_dk_anti_magic_shell_self_AuraScript::Absorb, EFFECT_0);
+ AfterEffectAbsorb += AuraEffectAbsorbFn(spell_dk_anti_magic_shell_self_AuraScript::Trigger, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_dk_anti_magic_shell_self_AuraScript();
+ }
+};
+
+// 50461 - Anti-Magic Zone
+class spell_dk_anti_magic_zone : public SpellScriptLoader
+{
+public:
+ spell_dk_anti_magic_zone() : SpellScriptLoader("spell_dk_anti_magic_zone") { }
+
+ class spell_dk_anti_magic_zone_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_dk_anti_magic_zone_AuraScript);
+
+ enum Spells
+ {
+ DK_SPELL_ANTI_MAGIC_SHELL_TALENT = 51052,
+ };
+
+ uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ return sSpellStore.LookupEntry(DK_SPELL_ANTI_MAGIC_SHELL_TALENT);
+ }
+
+ void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
+ {
+ SpellEntry const * talentSpell = sSpellStore.LookupEntry(DK_SPELL_ANTI_MAGIC_SHELL_TALENT);
+ amount = SpellMgr::CalculateSpellEffectAmount(talentSpell, EFFECT_0, GetCaster());
+ // assume caster is a player here
+ if (Unit * caster = GetCaster())
+ amount += 2 * caster->ToPlayer()->GetTotalAttackPowerValue(BASE_ATTACK);
+ }
+
+ void Absorb(AuraEffect * /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ absorbAmount = CalculatePctN(dmgInfo.GetDamage(), absorbPct);
+ }
+
+ void Register()
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_anti_magic_zone_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_dk_anti_magic_zone_AuraScript::Absorb, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_dk_anti_magic_zone_AuraScript();
+ }
+};
+
// 49158 Corpse Explosion (51325, 51326, 51327, 51328)
class spell_dk_corpse_explosion : public SpellScriptLoader
{
@@ -168,9 +327,15 @@ public:
PrepareAuraScript(spell_dk_spell_deflection_AuraScript);
uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
{
- absorbPct = amount;
// Set absorbtion amount to unlimited
amount = -1;
}
@@ -195,11 +360,83 @@ public:
}
};
+// 52284 - Will of the Necropolis
+class spell_dk_will_of_the_necropolis : public SpellScriptLoader
+{
+public:
+ spell_dk_will_of_the_necropolis() : SpellScriptLoader("spell_dk_will_of_the_necropolis") { }
+
+ class spell_dk_will_of_the_necropolis_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_dk_will_of_the_necropolis_AuraScript);
+
+ enum Spells
+ {
+ DK_SPELL_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189,
+ DK_SPELL_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284,
+ };
+ bool Validate(SpellEntry const *spellEntry)
+ {
+ // can't use other spell than will of the necropolis due to spell_ranks dependency
+ if (sSpellMgr->GetFirstSpellInChain(DK_SPELL_WILL_OF_THE_NECROPOLIS_AURA_R1) != sSpellMgr->GetFirstSpellInChain(spellEntry->Id))
+ return false;
+
+ uint8 rank = sSpellMgr->GetSpellRank(spellEntry->Id);
+ if (!sSpellMgr->GetSpellWithRank(DK_SPELL_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank, true))
+ return false;
+
+ return true;
+ }
+
+ uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
+ void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
+ {
+ // Set absorbtion amount to unlimited
+ amount = -1;
+ }
+
+ void Absorb(AuraEffect * /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ // min pct of hp is stored in effect 0 of talent spell
+ uint32 rank = sSpellMgr->GetSpellRank(GetSpellProto()->Id);
+ SpellEntry const * talentProto = sSpellStore.LookupEntry(sSpellMgr->GetSpellWithRank(DK_SPELL_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank));
+
+ int32 remainingHp = int32(GetTarget()->GetHealth() - dmgInfo.GetDamage());
+ int32 minHp = int32(GetTarget()->CountPctFromMaxHealth(SpellMgr::CalculateSpellEffectAmount(talentProto, EFFECT_0, GetCaster())));
+
+ // Damage that would take you below [effect0] health or taken while you are at [effect0]
+ if (remainingHp < minHp)
+ absorbAmount = CalculatePctN(dmgInfo.GetDamage(), absorbPct);
+ }
+
+ void Register()
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_will_of_the_necropolis_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_dk_will_of_the_necropolis_AuraScript::Absorb, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_dk_will_of_the_necropolis_AuraScript();
+ }
+};
void AddSC_deathknight_spell_scripts()
{
+ new spell_dk_anti_magic_shell_raid();
+ new spell_dk_anti_magic_shell_self();
+ new spell_dk_anti_magic_zone();
new spell_dk_corpse_explosion();
new spell_dk_runic_power_feed();
new spell_dk_scourge_strike();
new spell_dk_spell_deflection();
+ new spell_dk_will_of_the_necropolis();
}
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index 47e5ad00a87..0e5c1dd95ef 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -94,9 +94,15 @@ public:
PrepareAuraScript(spell_dru_moonkin_form_passive_AuraScript);
uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
{
- absorbPct = amount;
// Set absorbtion amount to unlimited
amount = -1;
}
@@ -132,9 +138,15 @@ public:
PrepareAuraScript(spell_dru_primal_tenacity_AuraScript);
uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_1, GetCaster());
+ return true;
+ }
+
void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
{
- absorbPct = amount;
// Set absorbtion amount to unlimited
amount = -1;
}
@@ -170,19 +182,22 @@ public:
PrepareAuraScript(spell_dru_savage_defense_AuraScript);
uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
{
- absorbPct = amount;
// Set absorbtion amount to unlimited
amount = -1;
}
void Absorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
{
- // don't waste charge when no dmg
- if (!dmgInfo.GetDamage())
- return;
- absorbAmount = CalculatePctN(GetTarget()->GetTotalAttackPowerValue(BASE_ATTACK), absorbPct);
+ absorbAmount = int32(CalculatePctN(GetTarget()->GetTotalAttackPowerValue(BASE_ATTACK), absorbPct));
aurEff->SetAmount(0);
}
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index e99d1e44548..0f664c3d829 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -25,6 +25,41 @@
#include "ScriptPCH.h"
#include "SpellAuraEffects.h"
+class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader
+{
+public:
+ spell_gen_absorb0_hitlimit1() : SpellScriptLoader("spell_gen_absorb0_hitlimit1") { }
+
+ class spell_gen_absorb0_hitlimit1_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_gen_absorb0_hitlimit1_AuraScript);
+
+ uint32 limit;
+
+ bool Load()
+ {
+ // Max absorb stored in 1 dummy effect
+ limit = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_1);
+ return true;
+ }
+
+ void Absorb(AuraEffect * /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ absorbAmount = std::min(limit, absorbAmount);
+ }
+
+ void Register()
+ {
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_gen_absorb0_hitlimit1_AuraScript::Absorb, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_gen_absorb0_hitlimit1_AuraScript();
+ }
+};
+
// 41337 Aura of Anger
class spell_gen_aura_of_anger : public SpellScriptLoader
{
@@ -562,6 +597,7 @@ class spell_gen_shroud_of_death : public SpellScriptLoader
void AddSC_generic_spell_scripts()
{
+ new spell_gen_absorb0_hitlimit1();
new spell_gen_aura_of_anger();
new spell_gen_burn_brutallus();
new spell_gen_leeching_swarm();
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index 901f36a3065..d4794e10b68 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -38,6 +38,39 @@ enum MageSpells
SPELL_MAGE_GLYPH_OF_BLAST_WAVE = 62126,
};
+class spell_mage_blast_wave : public SpellScriptLoader
+{
+ public:
+ spell_mage_blast_wave() : SpellScriptLoader("spell_mage_blast_wave") { }
+
+ class spell_mage_blast_wave_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_blast_wave_SpellScript)
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ if (!sSpellStore.LookupEntry(SPELL_MAGE_GLYPH_OF_BLAST_WAVE))
+ return false;
+ return true;
+ }
+
+ void HandleKnockBack(SpellEffIndex effIndex)
+ {
+ if (GetCaster()->HasAura(SPELL_MAGE_GLYPH_OF_BLAST_WAVE))
+ PreventHitDefaultEffect(effIndex);
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_mage_blast_wave_SpellScript::HandleKnockBack, EFFECT_2, SPELL_EFFECT_KNOCK_BACK);
+ }
+ };
+
+ SpellScript * GetSpellScript() const
+ {
+ return new spell_mage_blast_wave_SpellScript();
+ }
+};
+
class spell_mage_cold_snap : public SpellScriptLoader
{
public:
@@ -176,43 +209,61 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader
}
};
-class spell_mage_blast_wave : public SpellScriptLoader
+// Frost Ward and Fire Ward
+class spell_mage_frost_warding_trigger : public SpellScriptLoader
{
- public:
- spell_mage_blast_wave() : SpellScriptLoader("spell_mage_blast_wave") { }
+public:
+ spell_mage_frost_warding_trigger() : SpellScriptLoader("spell_mage_frost_warding_trigger") { }
- class spell_mage_blast_wave_SpellScript : public SpellScript
+ class spell_mage_frost_warding_trigger_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mage_frost_warding_trigger_AuraScript);
+
+ enum Spells
{
- PrepareSpellScript(spell_mage_blast_wave_SpellScript)
- bool Validate(SpellEntry const * /*spellEntry*/)
- {
- if (!sSpellStore.LookupEntry(SPELL_MAGE_GLYPH_OF_BLAST_WAVE))
- return false;
- return true;
- }
+ SPELL_MAGE_FROST_WARDING_TRIGGERED = 57776,
+ SPELL_MAGE_FROST_WARDING_R1 = 28332,
+ };
- void HandleKnockBack(SpellEffIndex effIndex)
- {
- if (GetCaster()->HasAura(SPELL_MAGE_GLYPH_OF_BLAST_WAVE))
- PreventHitDefaultEffect(effIndex);
- }
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ return sSpellStore.LookupEntry(SPELL_MAGE_FROST_WARDING_TRIGGERED)
+ && sSpellStore.LookupEntry(SPELL_MAGE_FROST_WARDING_R1);
+ }
- void Register()
+ void Absorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit * target = GetTarget();
+ if (AuraEffect * talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_FROST_WARDING_R1, EFFECT_0))
{
- OnEffect += SpellEffectFn(spell_mage_blast_wave_SpellScript::HandleKnockBack, EFFECT_2, SPELL_EFFECT_KNOCK_BACK);
+ int32 chance = SpellMgr::CalculateSpellEffectAmount(talentAurEff->GetSpellProto(), EFFECT_1);
+
+ if (roll_chance_i(chance))
+ {
+ absorbAmount = dmgInfo.GetDamage();
+ int32 bp = absorbAmount;
+ target->CastCustomSpell(target, SPELL_MAGE_FROST_WARDING_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff);
+ }
}
- };
+ }
- SpellScript * GetSpellScript() const
+ void Register()
{
- return new spell_mage_blast_wave_SpellScript();
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_mage_frost_warding_trigger_AuraScript::Absorb, EFFECT_0);
}
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_mage_frost_warding_trigger_AuraScript();
+ }
};
void AddSC_mage_spell_scripts()
{
+ new spell_mage_blast_wave;
new spell_mage_cold_snap;
+ new spell_mage_frost_warding_trigger();
new spell_mage_polymorph_cast_visual;
new spell_mage_summon_water_elemental;
- new spell_mage_blast_wave;
}
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index b53f172bfdf..828fa5de699 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -39,6 +39,82 @@ enum PaladinSpells
SPELL_BLESSING_OF_LOWER_CITY_SHAMAN = 37881,
};
+// 31850 - Ardent Defender
+class spell_pal_ardent_defender : public SpellScriptLoader
+{
+public:
+ spell_pal_ardent_defender() : SpellScriptLoader("spell_pal_ardent_defender") { }
+
+ class spell_pal_ardent_defender_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_pal_ardent_defender_AuraScript);
+
+ uint32 absorbPct, healPct;
+
+ enum Spell
+ {
+ PAL_SPELL_ARDENT_DEFENDER_HEAL = 66235,
+ };
+
+ bool Load()
+ {
+ healPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_1);
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0);
+ return GetUnitOwner()->ToPlayer();
+ }
+
+ void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
+ {
+ // Set absorbtion amount to unlimited
+ amount = -1;
+ }
+
+ void Absorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit * pVictim = GetTarget();
+ int32 remainingHealth = pVictim->GetHealth() - dmgInfo.GetDamage();
+ uint32 allowedHealth = pVictim->CountPctFromMaxHealth(35);
+ // If damage kills us
+ if (remainingHealth <= 0 && !pVictim->ToPlayer()->HasSpellCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL))
+ {
+ // Cast healing spell, completely avoid damage
+ absorbAmount = dmgInfo.GetDamage();
+
+ uint32 defenseSkillValue = pVictim->GetDefenseSkillValue();
+ // Max heal when defense skill denies critical hits from raid bosses
+ // Formula: max defense at level + 140 (raiting from gear)
+ uint32 reqDefForMaxHeal = pVictim->getLevel() * 5 + 140;
+ float pctFromDefense = (defenseSkillValue >= reqDefForMaxHeal)
+ ? 1.0f
+ : float(defenseSkillValue) / float(reqDefForMaxHeal);
+
+ int32 healAmount = int32(pVictim->CountPctFromMaxHealth(uint32(healPct * pctFromDefense)));
+ pVictim->CastCustomSpell(pVictim, PAL_SPELL_ARDENT_DEFENDER_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff);
+ pVictim->ToPlayer()->AddSpellCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL, 0, time(NULL) + 120);
+ }
+ else if (remainingHealth < int32(allowedHealth))
+ {
+ // Reduce damage that brings us under 35% (or full damage if we are already under 35%) by x%
+ uint32 damageToReduce = (pVictim->GetHealth() < allowedHealth)
+ ? dmgInfo.GetDamage()
+ : allowedHealth - remainingHealth;
+ absorbAmount = CalculatePctN(damageToReduce, absorbPct);
+ }
+ }
+
+ void Register()
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pal_ardent_defender_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_pal_ardent_defender_AuraScript::Absorb, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_pal_ardent_defender_AuraScript();
+ }
+};
+
class spell_pal_blessing_of_faith : public SpellScriptLoader
{
public:
@@ -253,6 +329,7 @@ public:
void AddSC_paladin_spell_scripts()
{
+ new spell_pal_ardent_defender();
new spell_pal_blessing_of_faith();
new spell_pal_blessing_of_sanctuary();
new spell_pal_guarded_by_the_light();
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 6631d840309..b149f182a1d 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -31,6 +31,66 @@ enum PriestSpells
PRIEST_SPELL_PENANCE_R1_HEAL = 47757,
};
+// Guardian Spirit
+class spell_pri_guardian_spirit : public SpellScriptLoader
+{
+public:
+ spell_pri_guardian_spirit() : SpellScriptLoader("spell_pri_guardian_spirit") { }
+
+ class spell_pri_guardian_spirit_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_pri_guardian_spirit_AuraScript);
+
+ uint32 healPct;
+
+ enum Spell
+ {
+ PRI_SPELL_GUARDIAN_SPIRIT_HEAL = 48153,
+ };
+
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ return sSpellStore.LookupEntry(PRI_SPELL_GUARDIAN_SPIRIT_HEAL);
+ }
+
+ bool Load()
+ {
+ healPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_1);
+ return true;
+ }
+
+ void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
+ {
+ // Set absorbtion amount to unlimited
+ amount = -1;
+ }
+
+ void Absorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit * target = GetTarget();
+ if (dmgInfo.GetDamage() < target->GetHealth())
+ return;
+
+ int32 healAmount = int32(target->CountPctFromMaxHealth(healPct));
+ // remove the aura now, we don't want 40% healing bonus
+ Remove(AURA_REMOVE_BY_ENEMY_SPELL);
+ target->CastCustomSpell(target, PRI_SPELL_GUARDIAN_SPIRIT_HEAL, &healAmount, NULL, NULL, true);
+ absorbAmount = dmgInfo.GetDamage();
+ }
+
+ void Register()
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_guardian_spirit_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_pri_guardian_spirit_AuraScript::Absorb, EFFECT_1);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_pri_guardian_spirit_AuraScript();
+ }
+};
+
class spell_pri_mana_burn : public SpellScriptLoader
{
public:
@@ -148,9 +208,59 @@ class spell_pri_penance : public SpellScriptLoader
}
};
+// Reflective Shield
+class spell_pri_reflective_shield_trigger : public SpellScriptLoader
+{
+public:
+ spell_pri_reflective_shield_trigger() : SpellScriptLoader("spell_pri_reflective_shield_trigger") { }
+
+ class spell_pri_reflective_shield_trigger_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_pri_reflective_shield_trigger_AuraScript);
+
+ enum Spells
+ {
+ SPELL_PRI_REFLECTIVE_SHIELD_TRIGGERED = 33619,
+ SPELL_PRI_REFLECTIVE_SHIELD_R1 = 33201,
+ };
+
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ return sSpellStore.LookupEntry(SPELL_PRI_REFLECTIVE_SHIELD_TRIGGERED) && sSpellStore.LookupEntry(SPELL_PRI_REFLECTIVE_SHIELD_R1);
+ }
+
+ void Trigger(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit * target = GetTarget();
+ if (dmgInfo.GetAttacker() == target)
+ return;
+ Unit * caster = GetCaster();
+ if (!caster)
+ return;
+ if (AuraEffect * talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_PRI_REFLECTIVE_SHIELD_R1, EFFECT_0))
+ {
+ int32 bp = CalculatePctN(absorbAmount, talentAurEff->GetAmount());
+ target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_PRI_REFLECTIVE_SHIELD_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff);
+ }
+ }
+
+ void Register()
+ {
+ AfterEffectAbsorb += AuraEffectAbsorbFn(spell_pri_reflective_shield_trigger_AuraScript::Trigger, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_pri_reflective_shield_trigger_AuraScript();
+ }
+};
+
void AddSC_priest_spell_scripts()
{
+ new spell_pri_guardian_spirit();
new spell_pri_mana_burn;
new spell_pri_pain_and_suffering_proc;
new spell_pri_penance;
+ new spell_pri_reflective_shield_trigger();
}
diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp
index ffae231839c..6d1afef3460 100644
--- a/src/server/scripts/Spells/spell_rogue.cpp
+++ b/src/server/scripts/Spells/spell_rogue.cpp
@@ -30,6 +30,76 @@ enum RogueSpells
ROGUE_SPELL_PREY_ON_THE_WEAK = 58670,
};
+// Cheat Death
+class spell_rog_cheat_death : public SpellScriptLoader
+{
+public:
+ spell_rog_cheat_death() : SpellScriptLoader("spell_rog_cheat_death") { }
+
+ class spell_rog_cheat_death_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_rog_cheat_death_AuraScript);
+
+ uint32 absorbChance;
+
+ enum Spell
+ {
+ ROG_SPELL_CHEAT_DEATH_COOLDOWN = 31231,
+ };
+
+ bool Validate(SpellEntry const * /*spellEntry*/)
+ {
+ return sSpellStore.LookupEntry(ROG_SPELL_CHEAT_DEATH_COOLDOWN);
+ }
+
+ bool Load()
+ {
+ absorbChance = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0);
+ return GetUnitOwner()->ToPlayer();
+ }
+
+ void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
+ {
+ // Set absorbtion amount to unlimited
+ amount = -1;
+ }
+
+ void Absorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit * target = GetTarget();
+ if (dmgInfo.GetDamage() < target->GetHealth())
+ return;
+ if (target->ToPlayer()->HasSpellCooldown(ROG_SPELL_CHEAT_DEATH_COOLDOWN))
+ return;
+ if (!roll_chance_i(absorbChance))
+ return;
+
+ target->CastSpell(target, ROG_SPELL_CHEAT_DEATH_COOLDOWN, true);
+ target->ToPlayer()->AddSpellCooldown(ROG_SPELL_CHEAT_DEATH_COOLDOWN, 0, time(NULL) + 60);
+
+ uint32 health10 = target->CountPctFromMaxHealth(10);
+
+ // hp > 10% - absorb hp till 10%
+ if (target->GetHealth() > health10)
+ absorbAmount = dmgInfo.GetDamage() - target->GetHealth() + health10;
+ // hp lower than 10% - absorb everything
+ else
+ absorbAmount = dmgInfo.GetDamage();
+ }
+
+ void Register()
+ {
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_cheat_death_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_rog_cheat_death_AuraScript::Absorb, EFFECT_0);
+ }
+ };
+
+ AuraScript *GetAuraScript() const
+ {
+ return new spell_rog_cheat_death_AuraScript();
+ }
+};
+
// 31130 - Nerves of Steel
class spell_rog_nerves_of_steel : public SpellScriptLoader
{
@@ -41,9 +111,15 @@ public:
PrepareAuraScript(spell_rog_nerves_of_steel_AuraScript);
uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
{
- absorbPct = amount;
// Set absorbtion amount to unlimited
amount = -1;
}
@@ -216,6 +292,7 @@ class spell_rog_shiv : public SpellScriptLoader
void AddSC_rogue_spell_scripts()
{
+ new spell_rog_cheat_death();
new spell_rog_nerves_of_steel();
new spell_rog_preparation();
new spell_rog_prey_on_the_weak();
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index bf8e179a438..7c59c5227ca 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -47,9 +47,15 @@ public:
PrepareAuraScript(spell_sha_astral_shift_AuraScript);
uint32 absorbPct;
+
+ bool Load()
+ {
+ absorbPct = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_0, GetCaster());
+ return true;
+ }
+
void CalculateAmount(AuraEffect const * /*aurEff*/, int32 & amount, bool & canBeRecalculated)
{
- absorbPct = amount;
// Set absorbtion amount to unlimited
amount = -1;
}