aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2021_04_19_00_world_priest_holy_words.sql17
-rw-r--r--src/server/game/Spells/SpellHistory.cpp75
-rw-r--r--src/server/game/Spells/SpellHistory.h10
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp8
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp83
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp2
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp2
7 files changed, 168 insertions, 29 deletions
diff --git a/sql/updates/world/master/2021_04_19_00_world_priest_holy_words.sql b/sql/updates/world/master/2021_04_19_00_world_priest_holy_words.sql
new file mode 100644
index 00000000000..073c084fcc2
--- /dev/null
+++ b/sql/updates/world/master/2021_04_19_00_world_priest_holy_words.sql
@@ -0,0 +1,17 @@
+-- Spell Proc
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_pri_holy_words');
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(63733, 'spell_pri_holy_words');
+
+-- Spell Procs
+-- Make holy words Proc on the following spells:
+-- 2060 Heal 0x1000
+-- 2061 Flash Heal 0x0800
+-- 596 Prayer of Healing 0x0200
+-- 139 Renew 0x0040
+-- 585 Smite 0x0080
+-- 0x1AC0
+
+DELETE FROM `spell_proc` WHERE `SpellId` IN (63733); -- Holy Words
+INSERT INTO `spell_proc` (`SpellId`,`SchoolMask`,`SpellFamilyName`,`SpellFamilyMask0`,`SpellFamilyMask1`,`SpellFamilyMask2`,`SpellFamilyMask3`,`ProcFlags`,`SpellTypeMask`,`SpellPhaseMask`,`HitMask`,`AttributesMask`,`DisableEffectsMask`,`ProcsPerMinute`,`Chance`,`Cooldown`,`Charges`) VALUES
+(63733, 0, 6, 0x1AC0, 0x0, 0x0, 0x0, 0, 7, 2, 0x403, 0x0, 0, 0, 0, 0, 0);
diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp
index 95eff17a30e..01ba9da7739 100644
--- a/src/server/game/Spells/SpellHistory.cpp
+++ b/src/server/game/Spells/SpellHistory.cpp
@@ -545,13 +545,7 @@ void SpellHistory::AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point
_categoryCooldowns[categoryId] = &cooldownEntry;
}
-void SpellHistory::ModifyCooldown(uint32 spellId, int32 cooldownModMs)
-{
- Clock::duration offset = std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(cooldownModMs));
- ModifyCooldown(spellId, offset);
-}
-
-void SpellHistory::ModifyCooldown(uint32 spellId, Clock::duration offset)
+void SpellHistory::ModifySpellCooldown(uint32 spellId, Clock::duration offset)
{
auto itr = _spellCooldowns.find(spellId);
if (!offset.count() || itr == _spellCooldowns.end())
@@ -574,6 +568,23 @@ void SpellHistory::ModifyCooldown(uint32 spellId, Clock::duration offset)
}
}
+void SpellHistory::ModifyCooldown(uint32 spellId, Clock::duration cooldownMod)
+{
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _owner->GetMap()->GetDifficultyID()))
+ ModifyCooldown(spellInfo, cooldownMod);
+}
+
+void SpellHistory::ModifyCooldown(SpellInfo const* spellInfo, Clock::duration cooldownMod)
+{
+ if (!cooldownMod.count())
+ return;
+
+ if (GetChargeRecoveryTime(spellInfo->ChargeCategoryId) > 0 && GetMaxCharges(spellInfo->ChargeCategoryId) > 0)
+ ModifyChargeRecoveryTime(spellInfo->ChargeCategoryId, cooldownMod);
+ else
+ ModifySpellCooldown(spellInfo->Id, cooldownMod);
+}
+
void SpellHistory::ResetCooldown(uint32 spellId, bool update /*= false*/)
{
auto itr = _spellCooldowns.find(spellId);
@@ -746,6 +757,30 @@ bool SpellHistory::ConsumeCharge(uint32 chargeCategoryId)
return false;
}
+void SpellHistory::ModifyChargeRecoveryTime(uint32 chargeCategoryId, Clock::duration cooldownMod)
+{
+ SpellCategoryEntry const* chargeCategoryEntry = sSpellCategoryStore.LookupEntry(chargeCategoryId);
+ if (!chargeCategoryEntry)
+ return;
+
+ auto itr = _categoryCharges.find(chargeCategoryId);
+ if (itr == _categoryCharges.end() || itr->second.empty())
+ return;
+
+ Clock::time_point now = GameTime::GetGameTimeSystemPoint();
+
+ for (ChargeEntry& entry : itr->second)
+ {
+ entry.RechargeStart += cooldownMod;
+ entry.RechargeEnd += cooldownMod;
+ }
+
+ while (!itr->second.empty() && itr->second.front().RechargeEnd < now)
+ itr->second.pop_front();
+
+ SendSetSpellCharges(chargeCategoryId, itr->second);
+}
+
void SpellHistory::RestoreCharge(uint32 chargeCategoryId)
{
auto itr = _categoryCharges.find(chargeCategoryId);
@@ -753,17 +788,7 @@ void SpellHistory::RestoreCharge(uint32 chargeCategoryId)
{
itr->second.pop_back();
- if (Player* player = GetPlayerOwner())
- {
- WorldPackets::Spells::SetSpellCharges setSpellCharges;
- setSpellCharges.Category = chargeCategoryId;
- if (!itr->second.empty())
- setSpellCharges.NextRecoveryTime = uint32(std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.front().RechargeEnd - Clock::now()).count());
- setSpellCharges.ConsumedCharges = uint8(itr->second.size());
- setSpellCharges.IsPet = player != _owner;
-
- player->SendDirectMessage(setSpellCharges.Write());
- }
+ SendSetSpellCharges(chargeCategoryId, itr->second);
}
}
@@ -874,6 +899,20 @@ void SpellHistory::SendClearCooldowns(std::vector<int32> const& cooldowns) const
}
}
+void SpellHistory::SendSetSpellCharges(uint32 chargeCategoryId, ChargeEntryCollection const& chargeCollection)
+{
+ if (Player* player = GetPlayerOwner())
+ {
+ WorldPackets::Spells::SetSpellCharges setSpellCharges;
+ setSpellCharges.Category = chargeCategoryId;
+ if (!chargeCollection.empty())
+ setSpellCharges.NextRecoveryTime = uint32(std::chrono::duration_cast<std::chrono::milliseconds>(chargeCollection.front().RechargeEnd - Clock::now()).count());
+ setSpellCharges.ConsumedCharges = uint8(chargeCollection.size());
+ setSpellCharges.IsPet = player != _owner;
+ player->SendDirectMessage(setSpellCharges.Write());
+ }
+}
+
void SpellHistory::GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, int32* cooldown, uint32* categoryId, int32* categoryCooldown)
{
ASSERT(cooldown || categoryId || categoryCooldown);
diff --git a/src/server/game/Spells/SpellHistory.h b/src/server/game/Spells/SpellHistory.h
index 2532da00139..a6bf6bab3a2 100644
--- a/src/server/game/Spells/SpellHistory.h
+++ b/src/server/game/Spells/SpellHistory.h
@@ -31,7 +31,6 @@ class Player;
class Spell;
class SpellInfo;
class Unit;
-struct SpellCategoryEntry;
/// Spell cooldown flags sent in SMSG_SPELL_COOLDOWN
enum SpellCooldownFlags
@@ -66,9 +65,10 @@ public:
Clock::time_point RechargeEnd;
};
+ typedef std::deque<ChargeEntry> ChargeEntryCollection;
typedef std::unordered_map<uint32 /*spellId*/, CooldownEntry> CooldownStorageType;
typedef std::unordered_map<uint32 /*categoryId*/, CooldownEntry*> CategoryCooldownStorageType;
- typedef std::unordered_map<uint32 /*categoryId*/, std::deque<ChargeEntry>> ChargeStorageType;
+ typedef std::unordered_map<uint32 /*categoryId*/, ChargeEntryCollection> ChargeStorageType;
typedef std::unordered_map<uint32 /*categoryId*/, Clock::time_point> GlobalCooldownStorageType;
explicit SpellHistory(Unit* owner) : _owner(owner), _schoolLockouts() { }
@@ -101,8 +101,8 @@ public:
}
void AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, uint32 categoryId, Clock::time_point categoryEnd, bool onHold = false);
- void ModifyCooldown(uint32 spellId, int32 cooldownModMs);
void ModifyCooldown(uint32 spellId, Clock::duration cooldownMod);
+ void ModifyCooldown(SpellInfo const* spellInfo, Clock::duration cooldownMod);
void ResetCooldown(uint32 spellId, bool update = false);
void ResetCooldown(CooldownStorageType::iterator& itr, bool update = false);
template<typename Predicate>
@@ -136,6 +136,7 @@ public:
// Charges
bool ConsumeCharge(uint32 chargeCategoryId);
+ void ModifyChargeRecoveryTime(uint32 chargeCategoryId, Clock::duration cooldownMod);
void RestoreCharge(uint32 chargeCategoryId);
void ResetCharges(uint32 chargeCategoryId);
void ResetAllCharges();
@@ -153,6 +154,7 @@ public:
private:
Player* GetPlayerOwner() const;
+ void ModifySpellCooldown(uint32 spellId, Clock::duration cooldownMod);
void SendClearCooldowns(std::vector<int32> const& cooldowns) const;
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
{
@@ -160,6 +162,8 @@ private:
return _spellCooldowns.erase(itr);
}
+ void SendSetSpellCharges(uint32 chargeCategoryId, ChargeEntryCollection const& chargeCollection);
+
static void GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, int32* cooldown, uint32* categoryId, int32* categoryCooldown);
Unit* _owner;
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index 3aba1eff8ae..9a91831da93 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -290,7 +290,7 @@ class spell_pal_crusader_might : public AuraScript
void HandleEffectProc(AuraEffect* aurEff, ProcEventInfo& /*eventInfo*/)
{
- GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_HOLY_SHOCK_R1, aurEff->GetAmount());
+ GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_HOLY_SHOCK_R1, Seconds(aurEff->GetAmount()));
}
void Register() override
@@ -437,7 +437,7 @@ class spell_pal_fist_of_justice : public AuraScript
{
int32 value = aurEff->GetAmount() / 10;
- GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_HAMMER_OF_JUSTICE, -value);
+ GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_HAMMER_OF_JUSTICE, Seconds(-value));
}
void Register() override
@@ -863,8 +863,8 @@ class spell_pal_righteous_protector : public AuraScript
{
int32 value = aurEff->GetAmount() * 100 * _baseHolyPowerCost->Amount;
- GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_AVENGING_WRATH, -value);
- GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_GUARDIAN_OF_ANCIENT_KINGS, -value);
+ GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_AVENGING_WRATH, Seconds(-value));
+ GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PALADIN_GUARDIAN_OF_ANCIENT_KINGS, Seconds(-value));
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 8a0995098af..d94b5cdef2a 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -25,8 +25,10 @@
#include "AreaTriggerAI.h"
#include "GridNotifiers.h"
#include "ObjectAccessor.h"
+#include "Log.h"
#include "Player.h"
#include "SpellAuraEffects.h"
+#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellScript.h"
@@ -43,7 +45,12 @@ enum PriestSpells
SPELL_PRIEST_BODY_AND_SOUL_SPEED = 65081,
SPELL_PRIEST_DIVINE_BLESSING = 40440,
SPELL_PRIEST_DIVINE_WRATH = 40441,
+ SPELL_PRIEST_FLASH_HEAL = 2061,
SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153,
+ SPELL_PRIEST_HEAL = 2060,
+ SPELL_PRIEST_HOLY_WORD_CHASTISE = 88625,
+ SPELL_PRIEST_HOLY_WORD_SANCTIFY = 34861,
+ SPELL_PRIEST_HOLY_WORD_SERENITY = 2050,
SPELL_PRIEST_ITEM_EFFICIENCY = 37595,
SPELL_PRIEST_LEAP_OF_FAITH_EFFECT = 92832,
SPELL_PRIEST_LEVITATE_EFFECT = 111759,
@@ -51,10 +58,13 @@ enum PriestSpells
SPELL_PRIEST_PENANCE_R1 = 47540,
SPELL_PRIEST_PENANCE_R1_DAMAGE = 47758,
SPELL_PRIEST_PENANCE_R1_HEAL = 47757,
+ SPELL_PRIEST_PRAYER_OF_HEALING = 596,
+ SPELL_PRIEST_RENEW = 139,
SPELL_PRIEST_RENEWED_HOPE = 197469,
SPELL_PRIEST_RENEWED_HOPE_EFFECT = 197470,
SPELL_PRIEST_SHIELD_DISCIPLINE_ENERGIZE = 47755,
SPELL_PRIEST_SHIELD_DISCIPLINE_PASSIVE = 197045,
+ SPELL_PRIEST_SMITE = 585,
SPELL_PRIEST_SPIRIT_OF_REDEMPTION = 27827,
SPELL_PRIEST_STRENGTH_OF_SOUL = 197535,
SPELL_PRIEST_STRENGTH_OF_SOUL_EFFECT = 197548,
@@ -358,6 +368,74 @@ class spell_pri_guardian_spirit : public SpellScriptLoader
}
};
+// 63733 - Holy Words
+class spell_pri_holy_words : public AuraScript
+{
+ PrepareAuraScript(spell_pri_holy_words);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo
+ ({
+ SPELL_PRIEST_HEAL,
+ SPELL_PRIEST_FLASH_HEAL,
+ SPELL_PRIEST_PRAYER_OF_HEALING,
+ SPELL_PRIEST_RENEW,
+ SPELL_PRIEST_SMITE,
+ SPELL_PRIEST_HOLY_WORD_CHASTISE,
+ SPELL_PRIEST_HOLY_WORD_SANCTIFY,
+ SPELL_PRIEST_HOLY_WORD_SERENITY
+ })
+ && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SERENITY, DIFFICULTY_NONE)->GetEffect(EFFECT_1)
+ && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SANCTIFY, DIFFICULTY_NONE)->GetEffect(EFFECT_2)
+ && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SANCTIFY, DIFFICULTY_NONE)->GetEffect(EFFECT_3)
+ && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_CHASTISE, DIFFICULTY_NONE)->GetEffect(EFFECT_1);
+ }
+
+ void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& eventInfo)
+ {
+ SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
+ if (!spellInfo)
+ return;
+
+ uint32 targetSpellId;
+ SpellEffIndex cdReductionEffIndex;
+ switch (spellInfo->Id)
+ {
+ case SPELL_PRIEST_HEAL:
+ case SPELL_PRIEST_FLASH_HEAL: // reduce Holy Word: Serenity cd by 6 seconds
+ targetSpellId = SPELL_PRIEST_HOLY_WORD_SERENITY;
+ cdReductionEffIndex = EFFECT_1;
+ // cdReduction = sSpellMgr->GetSpellInfo(SPELL_PRIEST_HOLY_WORD_SERENITY, GetCastDifficulty())->GetEffect(EFFECT_1)->CalcValue(player);
+ break;
+ case SPELL_PRIEST_PRAYER_OF_HEALING: // reduce Holy Word: Sanctify cd by 6 seconds
+ targetSpellId = SPELL_PRIEST_HOLY_WORD_SANCTIFY;
+ cdReductionEffIndex = EFFECT_2;
+ break;
+ case SPELL_PRIEST_RENEW: // reuce Holy Word: Sanctify cd by 2 seconds
+ targetSpellId = SPELL_PRIEST_HOLY_WORD_SANCTIFY;
+ cdReductionEffIndex = EFFECT_3;
+ break;
+ case SPELL_PRIEST_SMITE: // reduce Holy Word: Chastise cd by 4 seconds
+ targetSpellId = SPELL_PRIEST_HOLY_WORD_CHASTISE;
+ cdReductionEffIndex = EFFECT_1;
+ break;
+ default:
+ TC_LOG_WARN("spells.priest", "HolyWords aura has been proced by an unknown spell: %u", GetSpellInfo()->Id);
+ return;
+ }
+
+ SpellInfo const* targetSpellInfo = sSpellMgr->AssertSpellInfo(targetSpellId, GetCastDifficulty());
+ int32 cdReduction = targetSpellInfo->GetEffect(cdReductionEffIndex)->CalcValue(GetTarget());
+ GetTarget()->GetSpellHistory()->ModifyCooldown(targetSpellInfo, Seconds(-cdReduction));
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_pri_holy_words::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
+};
+
// 40438 - Priest Tier 6 Trinket
class spell_pri_item_t6_trinket : public SpellScriptLoader
{
@@ -459,9 +537,9 @@ public:
}
};
- SpellScript* GetSpellScript() const
+ SpellScript* GetSpellScript() const override
{
- return new spell_pri_levitate_SpellScript;
+ return new spell_pri_levitate_SpellScript();
}
};
@@ -1134,6 +1212,7 @@ void AddSC_priest_spell_scripts()
new spell_pri_atonement_triggered();
new spell_pri_divine_hymn();
new spell_pri_guardian_spirit();
+ RegisterAuraScript(spell_pri_holy_words);
new spell_pri_item_t6_trinket();
new spell_pri_leap_of_faith_effect_trigger();
new spell_pri_levitate();
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 618cb45e30f..cdef3647137 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -850,7 +850,7 @@ class spell_sha_item_t10_elemental_2p_bonus : public SpellScriptLoader
{
PreventDefaultAction();
if (Player* target = GetTarget()->ToPlayer())
- target->GetSpellHistory()->ModifyCooldown(SPELL_SHAMAN_ELEMENTAL_MASTERY, -aurEff->GetAmount());
+ target->GetSpellHistory()->ModifyCooldown(SPELL_SHAMAN_ELEMENTAL_MASTERY, Milliseconds(-aurEff->GetAmount()));
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 3e9d168ed12..555748be8ab 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -571,7 +571,7 @@ public:
void HandleAfterCast()
{
if (_targetCount >= uint32(GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue()))
- GetCaster()->ToPlayer()->GetSpellHistory()->ModifyCooldown(GetSpellInfo()->Id, -(GetSpellInfo()->GetEffect(EFFECT_3)->CalcValue() * IN_MILLISECONDS));
+ GetCaster()->ToPlayer()->GetSpellHistory()->ModifyCooldown(GetSpellInfo()->Id, Seconds(-GetSpellInfo()->GetEffect(EFFECT_3)->CalcValue()));
}
void Register() override