diff --git a/sql/scriptdev2/spell.sql b/sql/scriptdev2/spell.sql index 6f4c0f737d..e1c26905af 100644 --- a/sql/scriptdev2/spell.sql +++ b/sql/scriptdev2/spell.sql @@ -264,6 +264,10 @@ INSERT INTO spell_scripts(Id, ScriptName) VALUES (38760,'spell_void_blast'), (33558,'spell_draw_shadows_trigger'), (34662,'spell_bear_command'), +(36815,'spell_shock_barrier'), +(39228,'spell_argussian_compass'), +(41341,'spell_balance_of_power'), +(41475,'spell_reflective_shield_malande'), (41624,'spell_enfeeble_removal'), (32264,'spell_shirrak_inhibit_magic'), (33332,'spell_suppression_blast'), @@ -634,6 +638,18 @@ INSERT INTO spell_scripts(Id, ScriptName) VALUES (15324,'spell_blackout'), (15325,'spell_blackout'), (15326,'spell_blackout'), +(17,'spell_power_word_shield_priest'), +(592,'spell_power_word_shield_priest'), +(600,'spell_power_word_shield_priest'), +(3747,'spell_power_word_shield_priest'), +(6065,'spell_power_word_shield_priest'), +(6066,'spell_power_word_shield_priest'), +(10898,'spell_power_word_shield_priest'), +(10899,'spell_power_word_shield_priest'), +(10900,'spell_power_word_shield_priest'), +(10901,'spell_power_word_shield_priest'), +(25217,'spell_power_word_shield_priest'), +(25218,'spell_power_word_shield_priest'), (27827,'spell_spirit_of_redemption_heal'), (32676,'spell_consume_magic'), (33076,'spell_prayer_of_mending'), @@ -817,6 +833,9 @@ INSERT INTO spell_scripts(Id, ScriptName) VALUES (6770,'spell_sap'), (2070,'spell_sap'), -- check ranks before changing (11297,'spell_sap'), +(31228,'spell_cheat_death_rogue'), +(31229,'spell_cheat_death_rogue'), +(31230,'spell_cheat_death_rogue'), (14185,'spell_preparation'), (14082,'spell_dirty_deeds'), (14083,'spell_dirty_deeds'), diff --git a/src/game/AI/ScriptDevAI/scripts/outland/black_temple/illidari_council.cpp b/src/game/AI/ScriptDevAI/scripts/outland/black_temple/illidari_council.cpp index 7f49c734e0..b9588575bb 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/black_temple/illidari_council.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/black_temple/illidari_council.cpp @@ -715,6 +715,31 @@ struct VerasDeadlyPoisonTick : public AuraScript } }; +// 41341 - Balance of Power +struct BalanceOfPower : public AuraScript +{ + void OnAbsorb(Aura* /*aura*/, int32& currentAbsorb, int32& remainingDamage, uint32& /*reflectedSpellId*/, int32& /*reflectDamage*/, bool& /*preventedDeath*/, bool& dropCharge) const override + { + // unused atm + remainingDamage += currentAbsorb; + currentAbsorb = 0; + dropCharge = false; + } +}; + +// 41475 - Reflective Shield +struct ReflectiveShieldMalande : public AuraScript +{ + void OnAbsorb(Aura* /*aura*/, int32& currentAbsorb, int32& remainingDamage, uint32& reflectedSpellId, int32& reflectDamage, bool& /*preventedDeath*/, bool& /*dropCharge*/) const override + { + if (remainingDamage < currentAbsorb) + reflectDamage = remainingDamage / 2; + else + reflectDamage = currentAbsorb / 2; + reflectedSpellId = 33619; + } +}; + void AddSC_boss_illidari_council() { Script* pNewScript = new Script; @@ -750,4 +775,6 @@ void AddSC_boss_illidari_council() RegisterSpellScript("spell_veras_vanish"); RegisterSpellScript("spell_veras_deadly_poison"); RegisterSpellScript("spell_veras_deadly_poison_tick"); + RegisterSpellScript("spell_balance_of_power"); + RegisterSpellScript("spell_reflective_shield_malande"); } diff --git a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp index f588f1f699..6ce527befd 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp @@ -1927,6 +1927,19 @@ struct GravityLapseKnockup : public AuraScript } }; +// 36815 - Shock Barrier +struct ShockBarrier : public AuraScript +{ + void OnAbsorb(Aura* /*aura*/, int32& currentAbsorb, int32& remainingDamage, uint32& reflectedSpellId, int32& reflectDamage, bool& /*preventedDeath*/, bool& /*dropCharge*/) const override + { + reflectedSpellId = 36822; + if (remainingDamage < currentAbsorb) + reflectDamage = remainingDamage / 100; + else + reflectDamage = currentAbsorb / 100; + } +}; + void AddSC_boss_kaelthas() { Script* pNewScript = new Script; @@ -1965,4 +1978,5 @@ void AddSC_boss_kaelthas() RegisterSpellScript("spell_nether_vapor_summon_parent"); RegisterSpellScript("spell_remove_weapons"); RegisterSpellScript("spell_gravity_lapse_knockup"); + RegisterSpellScript("spell_shock_barrier"); } diff --git a/src/game/AI/ScriptDevAI/scripts/world/item_scripts.cpp b/src/game/AI/ScriptDevAI/scripts/world/item_scripts.cpp index 1cbcb6f602..755d21104a 100644 --- a/src/game/AI/ScriptDevAI/scripts/world/item_scripts.cpp +++ b/src/game/AI/ScriptDevAI/scripts/world/item_scripts.cpp @@ -322,6 +322,18 @@ struct OrbOfDeception : public AuraScript } }; +// 39228 - Argussian Compass +struct ArgussianCompass : public AuraScript +{ + void OnAbsorb(Aura* aura, int32& currentAbsorb, int32& /*remainingDamage*/, uint32& /*reflectedSpellId*/, int32& /*reflectDamage*/, bool& /*preventedDeath*/, bool& /*dropCharge*/) const override + { + // Max absorb stored in 1 dummy effect + int32 max_absorb = aura->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1); + if (max_absorb < currentAbsorb) + currentAbsorb = max_absorb; + } +}; + void AddSC_item_scripts() { Script* pNewScript = new Script; @@ -354,4 +366,5 @@ void AddSC_item_scripts() RegisterSpellScript("spell_reduced_proc_chance_past60"); RegisterSpellScript("spell_banish_exile"); RegisterSpellScript("spell_orb_of_deception"); + RegisterSpellScript("spell_argussian_compass"); } diff --git a/src/game/Entities/Unit.cpp b/src/game/Entities/Unit.cpp index 44b60dadf3..ac78eab070 100644 --- a/src/game/Entities/Unit.cpp +++ b/src/game/Entities/Unit.cpp @@ -2431,14 +2431,14 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa if (!IsAlive() || !damage) return; - int32 RemainingDamage = int32(damage); + int32 remainingDamage = int32(damage); // Magic damage, check for resists if (canResist && (schoolMask & SPELL_SCHOOL_MASK_MAGIC) && (!binary || damagetype == DOT)) { const float multiplier = Unit::RollMagicResistanceMultiplierOutcomeAgainst(caster, this, schoolMask, damagetype, binary); *resist = int32(int64(damage) * multiplier); - RemainingDamage -= *resist; + remainingDamage -= *resist; } else *resist = 0; @@ -2453,7 +2453,7 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa // full absorb cases (by chance) /* none cases, but preserve for better backporting conflict resolve AuraList const& vAbsorb = GetAurasByType(SPELL_AURA_SCHOOL_ABSORB); - for(AuraList::const_iterator i = vAbsorb.begin(); i != vAbsorb.end() && RemainingDamage > 0; ++i) + for(AuraList::const_iterator i = vAbsorb.begin(); i != vAbsorb.end() && remainingDamage > 0; ++i) { // only work with proper school mask damage Modifier* i_mod = (*i)->GetModifier(); @@ -2469,7 +2469,7 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa // absorb without mana cost AuraList const& vSchoolAbsorb = GetAurasByType(SPELL_AURA_SCHOOL_ABSORB); - for (AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i) + for (AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && remainingDamage > 0; ++i) { Modifier* mod = (*i)->GetModifier(); if (!(mod->m_miscvalue & schoolMask)) @@ -2478,7 +2478,7 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa SpellEntry const* spellProto = (*i)->GetSpellProto(); // Max Amount can be absorbed by this aura - int32 currentAbsorb = mod->m_amount; + int32 currentAbsorb = mod->m_amount; // Found empty aura (impossible but..) if (currentAbsorb <= 0) @@ -2487,125 +2487,18 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa continue; } - // Handle custom absorb auras - // TODO: try find better way - - switch (spellProto->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - switch (spellProto->Id) - { - case 36815: // Shock Barrier - Kael'Thas - { - reflectSpell = 36822; - if (RemainingDamage < currentAbsorb) - reflectDamage = RemainingDamage / 100; - else - reflectDamage = currentAbsorb / 100; - break; - } - case 39228: // Argussian Compass - { - // Max absorb stored in 1 dummy effect - int32 max_absorb = spellProto->CalculateSimpleValue(EFFECT_INDEX_1); - if (max_absorb < currentAbsorb) - currentAbsorb = max_absorb; - break; - } - case 41341: // Balance of Power - { - continue; // unused atm - } - case 41475: // Reflective Shield (Lady Malande boss) - { - if (RemainingDamage < currentAbsorb) - reflectDamage = RemainingDamage / 2; - else - reflectDamage = currentAbsorb / 2; - reflectSpell = 33619; - reflectTriggeredBy = *i; - break; - } - default: - break; - } - break; - } - case SPELLFAMILY_ROGUE: - { - switch (spellProto->Id) - { - case 31228: // Cheat Death - case 31229: - case 31230: - { - if (!preventDeathAura && - GetTypeId() == TYPEID_PLAYER && // Only players - IsSpellReady(31231) && - // Only if no cooldown - roll_chance_i((*i)->GetModifier()->m_amount)) - // Only if roll - { - preventDeathAura = (*i); - } - // always skip this spell in charge dropping, absorb amount calculation since it has chance as m_amount and doesn't need to absorb any damage - continue; - } - } - break; - } - case SPELLFAMILY_PRIEST: - { - // Reflective Shield - if (spellProto->IsFitToFamilyMask(uint64(0x0000000000000001)) && canReflect && caster) - { - if (caster == this) - break; - Unit* caster = (*i)->GetCaster(); - if (!caster) - break; - AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for (auto k : vOverRideCS) - { - switch (k->GetModifier()->m_miscvalue) - { - case 5065: // Rank 1 - case 5064: // Rank 2 - case 5063: // Rank 3 - case 5062: // Rank 4 - case 5061: // Rank 5 - { - if (RemainingDamage >= currentAbsorb) - reflectDamage = k->GetModifier()->m_amount * currentAbsorb / 100; - else - reflectDamage = k->GetModifier()->m_amount * RemainingDamage / 100; - reflectSpell = 33619; - reflectTriggeredBy = *i; - } break; - default: break; - } - } - break; - } - break; - } - default: - break; - } - // currentAbsorb - damage can be absorbed by shield // If need absorb less damage - if (RemainingDamage < currentAbsorb) - currentAbsorb = RemainingDamage; + if (remainingDamage < currentAbsorb) + currentAbsorb = remainingDamage; - bool preventedDeath = false; + bool preventedDeath = preventDeathAura != nullptr; bool dropCharge = true; - (*i)->OnAbsorb(currentAbsorb, RemainingDamage, reflectSpell, reflectDamage, preventedDeath, dropCharge); + (*i)->OnAbsorb(currentAbsorb, remainingDamage, reflectSpell, reflectDamage, preventedDeath, dropCharge); if (preventedDeath) preventDeathAura = (*i); - RemainingDamage -= currentAbsorb; + remainingDamage -= currentAbsorb; if (!IsPassiveSpell(spellProto)) { @@ -2643,7 +2536,7 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa // absorb by mana cost AuraList const& vManaShield = GetAurasByType(SPELL_AURA_MANA_SHIELD); - for (AuraList::const_iterator i = vManaShield.begin(), next; i != vManaShield.end() && RemainingDamage > 0; i = next) + for (AuraList::const_iterator i = vManaShield.begin(), next; i != vManaShield.end() && remainingDamage > 0; i = next) { next = i; ++next; @@ -2652,10 +2545,10 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa continue; int32 currentAbsorb; - if (RemainingDamage >= (*i)->GetModifier()->m_amount) + if (remainingDamage >= (*i)->GetModifier()->m_amount) currentAbsorb = (*i)->GetModifier()->m_amount; else - currentAbsorb = RemainingDamage; + currentAbsorb = remainingDamage; if (float manaMultiplier = (*i)->GetSpellProto()->EffectMultipleValue[(*i)->GetEffIndex()]) { @@ -2679,14 +2572,14 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa next = vManaShield.begin(); } - RemainingDamage -= currentAbsorb; + remainingDamage -= currentAbsorb; } // only split damage if not damaging yourself if (caster && caster != this) { AuraList const& vSplitDamageFlat = GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); - for (AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next) + for (AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && remainingDamage >= 0; i = next) { next = i; ++next; @@ -2700,12 +2593,12 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa continue; int32 currentAbsorb; - if (RemainingDamage >= (*i)->GetModifier()->m_amount) + if (remainingDamage >= (*i)->GetModifier()->m_amount) currentAbsorb = (*i)->GetModifier()->m_amount; else - currentAbsorb = RemainingDamage; + currentAbsorb = remainingDamage; - RemainingDamage -= currentAbsorb; + remainingDamage -= currentAbsorb; if (caster->IsImmuneToDamage(schoolMask)) { @@ -2724,7 +2617,7 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa } AuraList const& vSplitDamagePct = GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); - for (AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next) + for (AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && remainingDamage >= 0; i = next) { next = i; ++next; @@ -2737,9 +2630,9 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa if (!caster || caster == this || !caster->IsInWorld() || !caster->IsAlive()) continue; - uint32 splitted = uint32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); + uint32 splitted = uint32(remainingDamage * (*i)->GetModifier()->m_amount / 100.0f); - RemainingDamage -= int32(splitted); + remainingDamage -= int32(splitted); if (caster->IsImmuneToDamage(schoolMask)) { @@ -2758,35 +2651,10 @@ void Unit::CalculateDamageAbsorbAndResist(Unit* caster, SpellSchoolMask schoolMa } // Apply death prevention spells effects - if (preventDeathAura && RemainingDamage >= (int32)GetHealth()) - { - SpellEntry const* spellInfo = preventDeathAura->GetSpellProto(); - switch (spellInfo->SpellFamilyName) - { - case SPELLFAMILY_ROGUE: - { - switch (spellInfo->Id) - { - case 31228: // Cheat Death - case 31229: - case 31230: - { - SpellEntry const* cheatDeath = sSpellTemplate.LookupEntry(31231); - CastSpell(this, cheatDeath, TRIGGERED_OLD_TRIGGERED); - AddCooldown(*cheatDeath, nullptr, false, 60 * IN_MILLISECONDS); // TODO this may be removed by fixing cooldown value in spell template - // with health > 10% lost health until health==10%, in other case no losses - uint32 health10 = GetMaxHealth() / 10; - RemainingDamage = GetHealth() > health10 ? GetHealth() - health10 : 0; - break; - } - default: break; - } - } - } - preventDeathAura->OnAuraDeathPrevention(RemainingDamage); - } + if (preventDeathAura && remainingDamage >= (int32)GetHealth()) + preventDeathAura->OnAuraDeathPrevention(remainingDamage); - *absorb = damage - RemainingDamage - *resist; + *absorb = damage - remainingDamage - *resist; } void Unit::CalculateAbsorbResistBlock(Unit* caster, SpellNonMeleeDamage* spellDamageInfo, SpellEntry const* spellProto, WeaponAttackType attType) diff --git a/src/game/Spells/Scripts/Scripting/ClassScripts/Priest.cpp b/src/game/Spells/Scripts/Scripting/ClassScripts/Priest.cpp index e3cf0ba66f..cdb1ded00a 100644 --- a/src/game/Spells/Scripts/Scripting/ClassScripts/Priest.cpp +++ b/src/game/Spells/Scripts/Scripting/ClassScripts/Priest.cpp @@ -187,6 +187,35 @@ struct PainSuppression : public AuraScript } }; +// 17 - Power Word: Shield +struct PowerWordShieldPriest : public AuraScript +{ + void OnAbsorb(Aura* aura, int32& currentAbsorb, int32& remainingDamage, uint32& reflectedSpellId, int32& reflectDamage, bool& /*preventedDeath*/, bool& /*dropCharge*/) const override + { + Unit* caster = aura->GetTarget(); + Unit::AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for (auto k : vOverRideCS) // 33201 - Reflective Shield + { + switch (k->GetModifier()->m_miscvalue) + { + case 5065: // Rank 1 + case 5064: // Rank 2 + case 5063: // Rank 3 + case 5062: // Rank 4 + case 5061: // Rank 5 + { + if (remainingDamage >= currentAbsorb) + reflectDamage = k->GetModifier()->m_amount * currentAbsorb / 100; + else + reflectDamage = k->GetModifier()->m_amount * remainingDamage / 100; + reflectedSpellId = 33619; + } break; + default: break; + } + } + } +}; + void LoadPriestScripts() { RegisterSpellScript("spell_consume_magic"); @@ -198,4 +227,5 @@ void LoadPriestScripts() RegisterSpellScript("spell_prayer_of_mending"); RegisterSpellScript("spell_pain_suppression"); RegisterSpellScript("spell_shadowfiend"); + RegisterSpellScript("spell_power_word_shield_priest"); } diff --git a/src/game/Spells/Scripts/Scripting/ClassScripts/Rogue.cpp b/src/game/Spells/Scripts/Scripting/ClassScripts/Rogue.cpp index 4232b53f93..b0217654f3 100644 --- a/src/game/Spells/Scripts/Scripting/ClassScripts/Rogue.cpp +++ b/src/game/Spells/Scripts/Scripting/ClassScripts/Rogue.cpp @@ -145,6 +145,34 @@ struct DirtyDeeds : public AuraScript } }; +// 31228 - Cheat Death +struct CheatDeathRogue : public AuraScript +{ + void OnAbsorb(Aura* aura, int32& currentAbsorb, int32& remainingDamage, uint32& /*reflectedSpellId*/, int32& /*reflectDamage*/, bool& preventedDeath, bool& dropCharge) const override + { + if (!preventedDeath && aura->GetTarget()->IsPlayer() && + aura->GetTarget()->IsSpellReady(31231) && + // Only if no cooldown + roll_chance_i(aura->GetModifier()->m_amount)) + // Only if roll + { + preventedDeath = true; + } + // always skip this spell in charge dropping, absorb amount calculation since it has chance as m_amount and doesn't need to absorb any damage + dropCharge = false; + } + + void OnAuraDeathPrevention(Aura* aura, int32& remainingDamage) const override + { + SpellEntry const* cheatDeath = sSpellTemplate.LookupEntry(31231); + aura->GetTarget()->CastSpell(nullptr, cheatDeath, TRIGGERED_OLD_TRIGGERED); + aura->GetHolder()->SetProcCooldown(std::chrono::seconds(60), aura->GetTarget()->GetMap()->GetCurrentClockTime()); + // with health > 10% lost health until health==10%, in other case no losses + uint32 health10 = aura->GetTarget()->GetMaxHealth() / 10; + remainingDamage = aura->GetTarget()->GetHealth() > health10 ? aura->GetTarget()->GetHealth() - health10 : 0; + } +}; + void LoadRogueScripts() { RegisterSpellScript("spell_preparation"); @@ -153,4 +181,5 @@ void LoadRogueScripts() RegisterSpellScript("spell_sap"); RegisterSpellScript("spell_setup_rogue"); RegisterSpellScript("spell_dirty_deeds"); + RegisterSpellScript("spell_cheat_death_rogue"); } \ No newline at end of file