From 3e028633bae8830edccda568ff81fe880a27515b Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Mon, 13 Oct 2025 13:23:31 -0400 Subject: [PATCH] Updated all spell scripts --- Source/Framework/Constants/SharedConst.cs | 4 +- Source/Framework/Util/CollectionExtensions.cs | 27 + Source/Game/DataStorage/CliDB.cs | 4 +- Source/Game/DataStorage/DB2Manager.cs | 4 +- .../Game/Entities/AreaTrigger/AreaTrigger.cs | 14 +- Source/Game/Entities/GameObject/GameObject.cs | 14 +- Source/Game/Entities/Object/WorldObject.cs | 4 +- Source/Game/Entities/Pet.cs | 2 +- Source/Game/Entities/Player/Player.Combat.cs | 2 +- Source/Game/Entities/Player/Player.DB.cs | 2 +- Source/Game/Entities/Player/Player.Spells.cs | 8 +- Source/Game/Entities/Player/Player.cs | 8 +- Source/Game/Entities/Player/PlayerTaxi.cs | 2 +- Source/Game/Entities/StatSystem.cs | 4 +- Source/Game/Entities/TemporarySummon.cs | 2 +- Source/Game/Entities/Unit/Unit.Fields.cs | 27 +- Source/Game/Entities/Unit/Unit.Pets.cs | 7 +- Source/Game/Entities/Unit/Unit.Spells.cs | 5 + Source/Game/Entities/Unit/Unit.cs | 9 +- Source/Game/Globals/ObjectManager.cs | 4 +- Source/Game/Handlers/CharacterHandler.cs | 2 +- Source/Game/Handlers/SpellHandler.cs | 2 +- Source/Game/Maps/GridNotifiers.cs | 21 + .../Networking/Packets/CharacterPackets.cs | 2 +- Source/Game/Scripting/ScriptManager.cs | 21 +- Source/Game/Scripting/SpellScript.cs | 6 +- Source/Game/Spells/Spell.cs | 12 +- Source/Game/Spells/SpellHistory.cs | 11 +- Source/Scripts/Spells/Azerite.cs | 1122 +- Source/Scripts/Spells/DeathKnight.cs | 2158 ++-- Source/Scripts/Spells/DemonHunter.cs | 2056 +++- Source/Scripts/Spells/Druid.cs | 4145 ++++--- Source/Scripts/Spells/Evoker.cs | 1015 +- Source/Scripts/Spells/Generic.cs | 10022 ++++++++-------- Source/Scripts/Spells/Hunter.cs | 2071 ++-- Source/Scripts/Spells/Item.cs | 8366 ++++++------- Source/Scripts/Spells/Mage.cs | 2930 +++-- Source/Scripts/Spells/Monk.cs | 1107 +- Source/Scripts/Spells/Paladin.cs | 2961 ++--- Source/Scripts/Spells/Pet.cs | 1647 +-- Source/Scripts/Spells/Priest.cs | 6244 +++++----- Source/Scripts/Spells/Quest.cs | 3076 ++--- Source/Scripts/Spells/Rogue.cs | 2275 ++-- Source/Scripts/Spells/Shaman.cs | 4839 +++++--- Source/Scripts/Spells/Warlock.cs | 2663 ++-- Source/Scripts/Spells/Warrior.cs | 991 +- 46 files changed, 33364 insertions(+), 26554 deletions(-) diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index 7df014d57..e734968bb 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -663,7 +663,7 @@ namespace Framework.Constants Hunter = 3, Rogue = 4, Priest = 5, - Deathknight = 6, + DeathKnight = 6, Shaman = 7, Mage = 8, Warlock = 9, @@ -675,7 +675,7 @@ namespace Framework.Constants Max = 15, ClassMaskAllPlayable = ((1 << (Warrior - 1)) | (1 << (Paladin - 1)) | (1 << (Hunter - 1)) | - (1 << (Rogue - 1)) | (1 << (Priest - 1)) | (1 << (Deathknight - 1)) | (1 << (Shaman - 1)) | + (1 << (Rogue - 1)) | (1 << (Priest - 1)) | (1 << (DeathKnight - 1)) | (1 << (Shaman - 1)) | (1 << (Mage - 1)) | (1 << (Warlock - 1)) | (1 << (Monk - 1)) | (1 << (Druid - 1)) | (1 << (DemonHunter - 1)) | (1 << (Evoker - 1))), ClassMaskAllCreatures = ((1 << (Warrior - 1)) | (1 << (Paladin - 1)) | (1 << (Rogue - 1)) | (1 << (Mage - 1))), diff --git a/Source/Framework/Util/CollectionExtensions.cs b/Source/Framework/Util/CollectionExtensions.cs index 4f36c29b9..6a6956311 100644 --- a/Source/Framework/Util/CollectionExtensions.cs +++ b/Source/Framework/Util/CollectionExtensions.cs @@ -203,6 +203,33 @@ namespace System.Collections.Generic while (list.Count <= index) list.Add(defaultValue); } + + public static void PartitionInPlace(this IList list, Func predicate) + { + int left = 0; + int right = list.Count - 1; + + while (left <= right) + { + while (left <= right && predicate(list[left])) + { + left++; + } + while (left <= right && !predicate(list[right])) + { + right--; + } + + if (left < right) + { + T temp = list[left]; + list[left] = list[right]; + list[right] = temp; + left++; + right--; + } + } + } } public interface ICheck diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index bbd7c76be..2183552c4 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -845,7 +845,7 @@ namespace Game.DataStorage return row.Rogue; case Class.Priest: return row.Priest; - case Class.Deathknight: + case Class.DeathKnight: return row.DeathKnight; case Class.Shaman: return row.Shaman; @@ -884,7 +884,7 @@ namespace Game.DataStorage return row.Rogue; case (int)Class.Priest: return row.Priest; - case (int)Class.Deathknight: + case (int)Class.DeathKnight: return row.DeathKnight; case (int)Class.Shaman: return row.Shaman; diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index 311bc5807..460551470 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -1842,7 +1842,7 @@ namespace Game.DataStorage { return playerClass switch { - Class.Deathknight => numTalentsAtLevel.NumTalentsDeathKnight, + Class.DeathKnight => numTalentsAtLevel.NumTalentsDeathKnight, Class.DemonHunter => numTalentsAtLevel.NumTalentsDemonHunter, _ => numTalentsAtLevel.NumTalents, }; @@ -1897,7 +1897,7 @@ namespace Game.DataStorage { switch (class_) { - case Class.Deathknight: + case Class.DeathKnight: return _pvpTalentSlotUnlock[slot].DeathKnightLevelRequired; case Class.DemonHunter: return _pvpTalentSlotUnlock[slot].DemonHunterLevelRequired; diff --git a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs index 304657b22..3cc8e72f5 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs @@ -637,7 +637,7 @@ namespace Game.Entities var conditions = Global.ConditionMgr.GetConditionsForAreaTrigger(GetTemplate().Id.Id, GetTemplate().Id.IsCustom); targetList.RemoveAll(target => { - if (GetCasterGuid() == target.GetGUID()) + if (GetCasterGUID() == target.GetGUID()) { if (HasActionSetFlag(AreaTriggerActionSetFlag.NotTriggeredbyCaster)) return true; @@ -921,7 +921,7 @@ namespace Game.Entities public Unit GetCaster() { - return Global.ObjAccessor.GetUnit(this, GetCasterGuid()); + return Global.ObjAccessor.GetUnit(this, GetCasterGUID()); } Unit GetTarget() @@ -1015,7 +1015,7 @@ namespace Game.Entities } } - float GetMaxSearchRadius() + public float GetMaxSearchRadius() { return m_areaTriggerData.BoundsRadius2D * CalcCurrentScale(); } @@ -1161,7 +1161,7 @@ namespace Game.Entities case AreaTriggerActionTypes.Cast: goto case AreaTriggerActionTypes.AddAura; case AreaTriggerActionTypes.AddAura: - unit.RemoveAurasDueToSpell(action.Param, GetCasterGuid()); + unit.RemoveAurasDueToSpell(action.Param, GetCasterGUID()); break; case AreaTriggerActionTypes.Tavern: Player player = unit.ToPlayer(); @@ -1574,9 +1574,9 @@ namespace Game.Entities public AreaTriggerCreateProperties GetCreateProperties() { return _areaTriggerCreateProperties; } - public override ObjectGuid GetCreatorGUID() { return GetCasterGuid(); } - public override ObjectGuid GetOwnerGUID() { return GetCasterGuid(); } - public ObjectGuid GetCasterGuid() { return m_areaTriggerData.Caster; } + public override ObjectGuid GetCreatorGUID() { return GetCasterGUID(); } + public override ObjectGuid GetOwnerGUID() { return GetCasterGUID(); } + public ObjectGuid GetCasterGUID() { return m_areaTriggerData.Caster; } public bool HasSplines() { return _spline != null && !_spline.Empty(); } public Spline GetSpline() { return _spline; } diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 5abbead8a..31c620043 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -3902,6 +3902,18 @@ namespace Game.Entities command.Execute(m_goTypeImpl); } + public int GetControllingTeam() + { + if (GetGoType() != GameObjectTypes.ControlZone) + return BattleGroundTeamId.Neutral; + + var controlZone = (ControlZone)m_goTypeImpl; + if (controlZone == null) + return BattleGroundTeamId.Neutral; + + return controlZone.GetControllingTeam(); + } + public void CreateModel() { m_model = GameObjectModel.Create(new GameObjectModelOwnerImpl(this)); @@ -4600,7 +4612,7 @@ namespace Game.Entities } } - int GetControllingTeam() + public int GetControllingTeam() { if (_value < GetMaxHordeValue()) return BattleGroundTeamId.Horde; diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 37718ac09..2f6c5cab2 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -2454,7 +2454,7 @@ namespace Game.Entities return spell.Prepare(targets.Targets, args.TriggeringAura); } - void SendPlayOrphanSpellVisual(Position sourceLocation, ObjectGuid target, uint spellVisualId, float travelSpeed, bool speedAsTime = false, bool withSourceOrientation = false) + public void SendPlayOrphanSpellVisual(Position sourceLocation, ObjectGuid target, uint spellVisualId, float travelSpeed, bool speedAsTime = false, bool withSourceOrientation = false) { PlayOrphanSpellVisual playOrphanSpellVisual = new(); playOrphanSpellVisual.SourceLocation = sourceLocation; @@ -2479,7 +2479,7 @@ namespace Game.Entities SendMessageToSet(playOrphanSpellVisual, true); } - void SendPlayOrphanSpellVisual(Position sourceLocation, Position targetLocation, uint spellVisualId, float travelSpeed, bool speedAsTime = false, bool withSourceOrientation = false) + public void SendPlayOrphanSpellVisual(Position sourceLocation, Position targetLocation, uint spellVisualId, float travelSpeed, bool speedAsTime = false, bool withSourceOrientation = false) { PlayOrphanSpellVisual playOrphanSpellVisual = new(); playOrphanSpellVisual.SourceLocation = sourceLocation; diff --git a/Source/Game/Entities/Pet.cs b/Source/Game/Entities/Pet.cs index a1654ac57..95e7ae3a7 100644 --- a/Source/Game/Entities/Pet.cs +++ b/Source/Game/Entities/Pet.cs @@ -1325,7 +1325,7 @@ namespace Game.Entities { case Class.Warlock: return GetCreatureTemplate().CreatureType == CreatureType.Demon; - case Class.Deathknight: + case Class.DeathKnight: return GetCreatureTemplate().CreatureType == CreatureType.Undead; case Class.Mage: return GetCreatureTemplate().CreatureType == CreatureType.Elemental; diff --git a/Source/Game/Entities/Player/Player.Combat.cs b/Source/Game/Entities/Player/Player.Combat.cs index ebdf612f9..a74aaf95b 100644 --- a/Source/Game/Entities/Player/Player.Combat.cs +++ b/Source/Game/Entities/Player/Player.Combat.cs @@ -472,7 +472,7 @@ namespace Game.Entities opponent.UpdateCriteria(CriteriaType.WinDuel, 1); // Credit for quest Death's Challenge - if (GetClass() == Class.Deathknight && opponent.GetQuestStatus(12733) == QuestStatus.Incomplete) + if (GetClass() == Class.DeathKnight && opponent.GetQuestStatus(12733) == QuestStatus.Incomplete) opponent.CastSpell(duel.Opponent, 52994, true); // Honor points after duel (the winner) - ImpConfig diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index 568e34816..75dd2081e 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -4276,7 +4276,7 @@ namespace Game.Entities // Define the required variables uint charDeleteMinLvl; - if (characterInfo.ClassId == Class.Deathknight) + if (characterInfo.ClassId == Class.DeathKnight) charDeleteMinLvl = WorldConfig.GetUIntValue(WorldCfg.ChardeleteDeathKnightMinLevel); else if (characterInfo.ClassId == Class.DemonHunter) charDeleteMinLvl = WorldConfig.GetUIntValue(WorldCfg.ChardeleteDemonHunterMinLevel); diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index e2053cbdd..b56ac8e4d 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -2088,7 +2088,7 @@ namespace Game.Entities ushort maxValue = GetMaxSkillValueForLevel(); if (rcInfo.HasFlag(SkillRaceClassInfoFlags.AlwaysMaxValue)) skillValue = maxValue; - else if (GetClass() == Class.Deathknight) + else if (GetClass() == Class.DeathKnight) skillValue = (ushort)Math.Min(Math.Max(1, (GetLevel() - 1) * 5), maxValue); SetSkill(skillId, 0, skillValue, maxValue); @@ -2104,7 +2104,7 @@ namespace Game.Entities ushort skillValue = 1; if (rcInfo.HasFlag(SkillRaceClassInfoFlags.AlwaysMaxValue)) skillValue = maxValue; - else if (GetClass() == Class.Deathknight) + else if (GetClass() == Class.DeathKnight) skillValue = (ushort)Math.Min(Math.Max(1, (GetLevel() - 1) * 5), maxValue); SetSkill(skillId, 1, skillValue, maxValue); @@ -3394,7 +3394,7 @@ namespace Game.Entities public void InitRunes() { - if (GetClass() != Class.Deathknight) + if (GetClass() != Class.DeathKnight) return; uint runeIndex = GetPowerIndex(PowerType.Runes); @@ -3414,7 +3414,7 @@ namespace Game.Entities public void UpdateAllRunesRegen() { - if (GetClass() != Class.Deathknight) + if (GetClass() != Class.DeathKnight) return; uint runeIndex = GetPowerIndex(PowerType.Runes); diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 4cd0a6f81..89c13349b 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -2072,7 +2072,7 @@ namespace Game.Entities } else { - if (GetClass() == Class.Deathknight && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977)) + if (GetClass() == Class.DeathKnight && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977)) { SendTransferAborted(teleportLocation.Location.GetMapId(), TransferAbortReason.UniqueMessage, 1); return false; @@ -2230,7 +2230,7 @@ namespace Game.Entities if (CliDB.ChrRacesStorage.LookupByKey(race).HasFlag(ChrRacesFlag.IsAlliedRace)) startLevel = WorldConfig.GetUIntValue(WorldCfg.StartAlliedRaceLevel); - if (playerClass == Class.Deathknight) + if (playerClass == Class.DeathKnight) { if (race == Race.PandarenAlliance || race == Race.PandarenHorde) startLevel = Math.Max(WorldConfig.GetUIntValue(WorldCfg.StartAlliedRaceLevel), startLevel); @@ -3587,7 +3587,7 @@ namespace Game.Entities Regenerate(power); // Runes act as cooldowns, and they don't need to send any data - if (GetClass() == Class.Deathknight) + if (GetClass() == Class.DeathKnight) { uint regeneratedRunes = 0; int regenIndex = 0; @@ -7393,7 +7393,7 @@ namespace Game.Entities if (node.HasFlag(TaxiNodeFlags.UsePlayerFavoriteMount) && preferredMountDisplay != 0) mount_display_id = preferredMountDisplay; else - mount_display_id = ObjectMgr.GetTaxiMountDisplayId(sourcenode, GetTeam(), npc == null || (sourcenode == 315 && GetClass() == Class.Deathknight)); + mount_display_id = ObjectMgr.GetTaxiMountDisplayId(sourcenode, GetTeam(), npc == null || (sourcenode == 315 && GetClass() == Class.DeathKnight)); // in spell case allow 0 model if ((mount_display_id == 0 && spellid == 0) || sourcepath == 0) diff --git a/Source/Game/Entities/Player/PlayerTaxi.cs b/Source/Game/Entities/Player/PlayerTaxi.cs index 1a8e18fee..a48cfc312 100644 --- a/Source/Game/Entities/Player/PlayerTaxi.cs +++ b/Source/Game/Entities/Player/PlayerTaxi.cs @@ -22,7 +22,7 @@ namespace Game.Entities m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / (1 * 64) + 1) * 8]; // class specific initial known nodes - if (chrClass == Class.Deathknight) + if (chrClass == Class.DeathKnight) { var factionMask = Player.TeamForRace(race) == Team.Horde ? DB2Manager.HordeTaxiNodesMask : DB2Manager.AllianceTaxiNodesMask; m_taximask = new byte[factionMask.Length]; diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index 0f1bd1c83..df8c4d0d2 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -917,7 +917,7 @@ namespace Game.Entities return Math.Max(missChance, 0f); } - float GetUnitCriticalChanceDone(WeaponAttackType attackType) + public float GetUnitCriticalChanceDone(WeaponAttackType attackType) { float chance = 0.0f; Player thisPlayer = ToPlayer(); @@ -1585,7 +1585,7 @@ namespace Game.Entities ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, oldVal, false); ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, newVal, true); ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, newVal, true); - if (GetClass() == Class.Deathknight) + if (GetClass() == Class.DeathKnight) UpdateAllRunesRegen(); break; case CombatRating.HasteRanged: diff --git a/Source/Game/Entities/TemporarySummon.cs b/Source/Game/Entities/TemporarySummon.cs index 575c2b2e3..32dd9a7eb 100644 --- a/Source/Game/Entities/TemporarySummon.cs +++ b/Source/Game/Entities/TemporarySummon.cs @@ -623,7 +623,7 @@ namespace Game.Entities { if (GetOwner().GetClass() == Class.Warlock || GetOwner().GetClass() == Class.Shaman // Fire Elemental - || GetOwner().GetClass() == Class.Deathknight) // Risen Ghoul + || GetOwner().GetClass() == Class.DeathKnight) // Risen Ghoul { petType = PetType.Summon; } diff --git a/Source/Game/Entities/Unit/Unit.Fields.cs b/Source/Game/Entities/Unit/Unit.Fields.cs index cd21d3bfa..3238bdf9d 100644 --- a/Source/Game/Entities/Unit/Unit.Fields.cs +++ b/Source/Game/Entities/Unit/Unit.Fields.cs @@ -312,11 +312,23 @@ namespace Game.Entities m_hitMask |= ProcFlagsHit.Absorb; } + public void ModifyDamage(ref int amount) + { + amount = Math.Max(amount, -((int)GetDamage())); + m_damage += (uint)amount; + } public void ModifyDamage(int amount) { amount = Math.Max(amount, -((int)GetDamage())); m_damage += (uint)amount; } + public void AbsorbDamage(ref uint amount) + { + amount = Math.Min(amount, GetDamage()); + m_absorb += amount; + m_damage -= amount; + m_hitMask |= ProcFlagsHit.Absorb; + } public void AbsorbDamage(uint amount) { amount = Math.Min(amount, GetDamage()); @@ -324,7 +336,7 @@ namespace Game.Entities m_damage -= amount; m_hitMask |= ProcFlagsHit.Absorb; } - public void ResistDamage(uint amount) + public void ResistDamage(ref uint amount) { amount = Math.Min(amount, GetDamage()); m_resist += amount; @@ -335,7 +347,18 @@ namespace Game.Entities m_hitMask &= ~(ProcFlagsHit.Normal | ProcFlagsHit.Critical); } } - void BlockDamage(uint amount) + public void ResistDamage(uint amount) + { + amount = Math.Min(amount, GetDamage()); + m_resist += amount; + m_damage -= amount; + if (m_damage == 0) + { + m_hitMask |= ProcFlagsHit.FullResist; + m_hitMask &= ~(ProcFlagsHit.Normal | ProcFlagsHit.Critical); + } + } + public void BlockDamage(ref uint amount) { amount = Math.Min(amount, GetDamage()); m_block += amount; diff --git a/Source/Game/Entities/Unit/Unit.Pets.cs b/Source/Game/Entities/Unit/Unit.Pets.cs index 530d74801..740f08778 100644 --- a/Source/Game/Entities/Unit/Unit.Pets.cs +++ b/Source/Game/Entities/Unit/Unit.Pets.cs @@ -528,14 +528,17 @@ namespace Game.Entities } } - public void GetAllMinionsByEntry(List Minions, uint entry) + public List GetAllMinionsByEntry(uint entry) { + List minions = new(); for (var i = 0; i < m_Controlled.Count; ++i) { Unit unit = m_Controlled[i]; if (unit.GetEntry() == entry && unit.IsSummon()) // minion, actually - Minions.Add(unit.ToTempSummon()); + minions.Add(unit.ToTempSummon()); } + + return minions; } public void RemoveAllMinionsByEntry(uint entry) diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index ea1ff2751..c496e0f11 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -2685,6 +2685,11 @@ namespace Game.Entities return m_appliedAuras.KeyValueList; } + public List GetAppliedAuras(uint key) + { + return m_appliedAuras.LookupByKey(key); + } + public Aura AddAura(uint spellId, Unit target) { if (target == null) diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 1137eb1a2..6d40bffda 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -3568,7 +3568,7 @@ namespace Game.Entities if (spell != null) spell.CallScriptOnResistAbsorbCalculateHandlers(damageInfo, ref resistedDamage, ref absorbIgnoringDamage); - damageInfo.ResistDamage(resistedDamage); + damageInfo.ResistDamage(ref resistedDamage); // 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 @@ -3608,9 +3608,10 @@ namespace Game.Entities // absorb must be smaller than the damage itself currentAbsorb = MathFunctions.RoundToInterval(ref currentAbsorb, 0, damageInfo.GetDamage()); - damageInfo.AbsorbDamage((uint)currentAbsorb); + uint temp = (uint)currentAbsorb; + damageInfo.AbsorbDamage(ref temp); + tempAbsorb = temp; - tempAbsorb = (uint)currentAbsorb; absorbAurEff.GetBase().CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, damageInfo, ref tempAbsorb); // Check if our aura is using amount to count heal @@ -3625,7 +3626,7 @@ namespace Game.Entities } if (!absorbAurEff.GetSpellInfo().HasAttribute(SpellAttr6.AbsorbCannotBeIgnore)) - damageInfo.ModifyDamage(absorbIgnoringDamage); + damageInfo.ModifyDamage(ref absorbIgnoringDamage); if (currentAbsorb != 0) { diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 58c7a8bc6..7c0da2adb 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -6139,7 +6139,7 @@ namespace Game switch ((SpellCategories)itemTemplate.Effects[0].SpellCategoryID) { case SpellCategories.Food: // food - count = characterLoadout.ChrClassID == (int)Class.Deathknight ? 10 : 4u; + count = characterLoadout.ChrClassID == (int)Class.DeathKnight ? 10 : 4u; break; case SpellCategories.Drink: // drink count = 2; @@ -6502,7 +6502,7 @@ namespace Game continue; // skip expansion classes if not playing with expansion - if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.WrathOfTheLichKing && _class == Class.Deathknight) + if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.WrathOfTheLichKing && _class == Class.DeathKnight) continue; if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.MistsOfPandaria && (race == Race.PandarenNeutral || race == Race.PandarenHorde || race == Race.PandarenAlliance)) diff --git a/Source/Game/Handlers/CharacterHandler.cs b/Source/Game/Handlers/CharacterHandler.cs index d9a1335cc..8a117130d 100644 --- a/Source/Game/Handlers/CharacterHandler.cs +++ b/Source/Game/Handlers/CharacterHandler.cs @@ -2018,7 +2018,7 @@ namespace Game { // i = (315 - 1) / 8 = 39 // m = 1 << ((315 - 1) % 8) = 4 - int deathKnightExtraNode = playerClass != Class.Deathknight || i != 39 ? 0 : 4; + int deathKnightExtraNode = playerClass != Class.DeathKnight || i != 39 ? 0 : 4; taximaskstream += (uint)(factionMask[i] | deathKnightExtraNode) + ' '; } diff --git a/Source/Game/Handlers/SpellHandler.cs b/Source/Game/Handlers/SpellHandler.cs index 7fa2f05bc..b4a2eae5a 100644 --- a/Source/Game/Handlers/SpellHandler.cs +++ b/Source/Game/Handlers/SpellHandler.cs @@ -630,7 +630,7 @@ namespace Game if (target == null) return; - if (target.GetCasterGuid() != _player.GetGUID()) + if (target.GetCasterGUID() != _player.GetGUID()) return; SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(target.m_areaTriggerData.SpellForVisuals, _player.GetMap().GetDifficultyID()); diff --git a/Source/Game/Maps/GridNotifiers.cs b/Source/Game/Maps/GridNotifiers.cs index 9fb46aca6..33274d4ce 100644 --- a/Source/Game/Maps/GridNotifiers.cs +++ b/Source/Game/Maps/GridNotifiers.cs @@ -687,6 +687,7 @@ namespace Game.Maps WorldObjectSearcherContinuation ShouldContinue(); void Insert(T obj); T GetResult(); + bool HasResult(); } class SearcherFirstObjectResult() : IResultInserter @@ -703,6 +704,11 @@ namespace Game.Maps result = obj; } + public bool HasResult() + { + return result != null; + } + public T GetResult() { return result; @@ -723,6 +729,11 @@ namespace Game.Maps result = obj; } + public bool HasResult() + { + return result != null; + } + public T GetResult() { return result; @@ -743,6 +754,11 @@ namespace Game.Maps container.Add(obj); } + public bool HasResult() + { + return !container.Empty(); + } + public T GetResult() { return default; @@ -876,6 +892,11 @@ namespace Game.Maps } } + public bool HasResult() + { + return resultInserter.HasResult(); + } + public T GetResult() { return resultInserter.GetResult(); diff --git a/Source/Game/Networking/Packets/CharacterPackets.cs b/Source/Game/Networking/Packets/CharacterPackets.cs index 7fcaa3d04..8ed00dbc5 100644 --- a/Source/Game/Networking/Packets/CharacterPackets.cs +++ b/Source/Game/Networking/Packets/CharacterPackets.cs @@ -152,7 +152,7 @@ namespace Game.Networking.Packets FirstLogin = atLoginFlags.HasAnyFlag(AtLoginFlags.FirstLogin); // show pet at selection character in character list only for non-ghost character - if (!playerFlags.HasAnyFlag(PlayerFlags.Ghost) && (ClassId == Class.Warlock || ClassId == Class.Hunter || ClassId == Class.Deathknight)) + if (!playerFlags.HasAnyFlag(PlayerFlags.Ghost) && (ClassId == Class.Warlock || ClassId == Class.Hunter || ClassId == Class.DeathKnight)) { CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(fields.Read(14)); if (creatureInfo != null) diff --git a/Source/Game/Scripting/ScriptManager.cs b/Source/Game/Scripting/ScriptManager.cs index b0527680c..b6583a4fe 100644 --- a/Source/Game/Scripting/ScriptManager.cs +++ b/Source/Game/Scripting/ScriptManager.cs @@ -74,7 +74,7 @@ namespace Game.Scripting var constructors = type.GetConstructors(); if (constructors.Length == 0) { - Log.outError(LogFilter.Scripts, "Script: {0} contains no Public Constructors. Can't load script.", type.Name); + Log.outError(LogFilter.Scripts, $"Script: {type.Name} contains no Public Constructors. Can't load script."); continue; } @@ -84,16 +84,15 @@ namespace Game.Scripting string name = type.Name; bool validArgs = true; - int i = 0; foreach (var constructor in constructors) { var parameters = constructor.GetParameters(); if (parameters.Length != attribute.Args.Length) continue; - foreach (var arg in constructor.GetParameters()) + for (var i = 0; i < parameters.Length; ++i) { - if (arg.ParameterType != attribute.Args[i++].GetType()) + if (attribute.Args[i] != null && attribute.Args[i].GetType() != parameters[i].ParameterType) { validArgs = false; break; @@ -110,6 +109,9 @@ namespace Game.Scripting continue; } + if (!attribute.Name.IsEmpty()) + name = attribute.Name; + switch (type.BaseType.Name) { case nameof(SpellScript): @@ -129,6 +131,9 @@ namespace Game.Scripting case nameof(ConversationAI): genericType = typeof(GenericConversationScript<>).MakeGenericType(type); break; + case nameof(BattlegroundScript): + genericType = typeof(GenericBattlegroundMapScript<>).MakeGenericType(type); + break; case "SpellScriptLoader": case "AuraScriptLoader": case "WorldScript": @@ -161,22 +166,16 @@ namespace Game.Scripting case "AchievementScript": case "BattlefieldScript": case "EventScript": - if (!attribute.Name.IsEmpty()) - name = attribute.Name; - if (attribute.Args.Empty()) Activator.CreateInstance(genericType); else - Activator.CreateInstance(genericType, new object[] { name }.Combine(attribute.Args)); + Activator.CreateInstance(genericType, name, attribute.Args); continue; default: genericType = typeof(GenericCreatureScript<>).MakeGenericType(type); break; } - if (!attribute.Name.IsEmpty()) - name = attribute.Name; - Activator.CreateInstance(genericType, name, attribute.Args); } } diff --git a/Source/Game/Scripting/SpellScript.cs b/Source/Game/Scripting/SpellScript.cs index 42592bbd1..deb2844ba 100644 --- a/Source/Game/Scripting/SpellScript.cs +++ b/Source/Game/Scripting/SpellScript.cs @@ -30,7 +30,7 @@ namespace Game.Scripting return true; } - public bool ValidateSpellInfo(params uint[] spellIds) + public static bool ValidateSpellInfo(params uint[] spellIds) { bool allValid = true; foreach (uint spellId in spellIds) @@ -45,7 +45,7 @@ namespace Game.Scripting return allValid; } - public bool ValidateSpellEffect(params (uint spellId, uint effectIndex)[] pairs) + public static bool ValidateSpellEffect(params (uint spellId, uint effectIndex)[] pairs) { bool allValid = true; foreach (var (spellId, effectIndex) in pairs) @@ -56,7 +56,7 @@ namespace Game.Scripting return allValid; } - public bool ValidateSpellEffect(uint spellId, uint effectIndex) + public static bool ValidateSpellEffect(uint spellId, uint effectIndex) { SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, Difficulty.None); if (spellInfo == null) diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index cd628cd40..5f286509d 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -4047,7 +4047,7 @@ namespace Game.Spells if ((m_caster.IsPlayer() || (m_caster.IsTypeId(TypeId.Unit) && m_caster.ToCreature().IsPet())) && m_powerCost.Any(cost => cost.Power != PowerType.Health)) castFlags |= SpellCastFlags.PowerLeftSelf; - if (m_caster.IsPlayer() && m_caster.ToPlayer().GetClass() == Class.Deathknight && + if (m_caster.IsPlayer() && m_caster.ToPlayer().GetClass() == Class.DeathKnight && HasPowerTypeCost(PowerType.Runes) && !_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.IgnorePowerCost)) { castFlags |= SpellCastFlags.NoGCD; // not needed, but it's being sent according to sniffs @@ -4820,7 +4820,7 @@ namespace Game.Spells if (player == null) return SpellCastResult.SpellCastOk; - if (player.GetClass() != Class.Deathknight) + if (player.GetClass() != Class.DeathKnight) return SpellCastResult.SpellCastOk; int readyRunes = 0; @@ -4836,7 +4836,7 @@ namespace Game.Spells void TakeRunePower(bool didHit) { - if (!m_caster.IsTypeId(TypeId.Player) || m_caster.ToPlayer().GetClass() != Class.Deathknight) + if (!m_caster.IsTypeId(TypeId.Player) || m_caster.ToPlayer().GetClass() != Class.DeathKnight) return; Player player = m_caster.ToPlayer(); @@ -4858,7 +4858,7 @@ namespace Game.Spells void RefundRunePower() { - if (!m_caster.IsPlayer() || m_caster.ToPlayer().GetClass() != Class.Deathknight) + if (!m_caster.IsPlayer() || m_caster.ToPlayer().GetClass() != Class.DeathKnight) return; Player player = m_caster.ToPlayer(); @@ -6578,7 +6578,7 @@ namespace Game.Spells return unit.HasUnitMovementFlag(MovementFlag.Forward | MovementFlag.StrafeLeft | MovementFlag.StrafeRight | MovementFlag.Falling) && !unit.IsWalking(); } - (float minRange, float maxRange) GetMinMaxRange(bool strict) + public (float minRange, float maxRange) GetMinMaxRange(bool strict) { float rangeMod = 0.0f; float minRange = 0.0f; @@ -8421,7 +8421,7 @@ namespace Game.Spells return SpellCastResult.SpellCastOk; } - int CalculateDamage(SpellEffectInfo spellEffectInfo, Unit target) + public int CalculateDamage(SpellEffectInfo spellEffectInfo, Unit target) { return CalculateDamage(spellEffectInfo, target, out _); } diff --git a/Source/Game/Spells/SpellHistory.cs b/Source/Game/Spells/SpellHistory.cs index 2ddc2f595..2d0ef1295 100644 --- a/Source/Game/Spells/SpellHistory.cs +++ b/Source/Game/Spells/SpellHistory.cs @@ -857,7 +857,7 @@ namespace Game.Spells _categoryCharges.Add(chargeCategoryId, new ChargeEntry(recoveryStart, TimeSpan.FromMilliseconds(chargeRecovery))); } - void ModifyChargeRecoveryTime(uint chargeCategoryId, TimeSpan cooldownMod) + public void ModifyChargeRecoveryTime(uint chargeCategoryId, TimeSpan cooldownMod) { var chargeCategoryEntry = CliDB.SpellCategoryStorage.LookupByKey(chargeCategoryId); if (chargeCategoryEntry == null) @@ -1119,12 +1119,19 @@ namespace Game.Spells } } - void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref uint categoryId) + public static void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref uint categoryId) { TimeSpan notUsed = TimeSpan.Zero; GetCooldownDurations(spellInfo, itemId, ref notUsed, ref categoryId, ref notUsed); } + public static void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref TimeSpan cooldown) + { + TimeSpan notUsed = TimeSpan.Zero; + uint notUsedId = 0; + GetCooldownDurations(spellInfo, itemId, ref cooldown, ref notUsedId, ref notUsed); + } + public static void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref TimeSpan cooldown, ref uint categoryId, ref TimeSpan categoryCooldown) { TimeSpan tmpCooldown = TimeSpan.MinValue; diff --git a/Source/Scripts/Spells/Azerite.cs b/Source/Scripts/Spells/Azerite.cs index 8e82d34f9..ce08ee88b 100644 --- a/Source/Scripts/Spells/Azerite.cs +++ b/Source/Scripts/Spells/Azerite.cs @@ -1,5 +1,5 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Game.Entities; @@ -8,582 +8,572 @@ using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using System.Linq; -namespace Scripts.Spells.Azerite +namespace Scripts.Spells.Azerite; + +struct SpellIds { - [Script] - class spell_azerite_gen_aura_calc_from_2nd_effect_triggered_spell : AuraScript + public const uint AgonySoulShardGain = 210067; + public const uint BlessedPortentsHeal = 280052; + public const uint BlessedPortentsTrait = 267889; + public const uint BracingChill = 272276; + public const uint BracingChillHeal = 272428; + public const uint BracingChillSearchJumpTarget = 272436; + public const uint BracingChillTrait = 267884; + public const uint ConcentratedMendingTrait = 267882; + public const uint DhSoulBarrier = 263648; + public const uint EchoingBladesTrait = 287649; + public const uint HunterCoordinatedAssault = 266779; + public const uint MageFrozenOrb = 84714; + public const uint StrengthInNumbersTrait = 271546; + public const uint StrengthInNumbersBuff = 271550; + public const uint TradewindsAllyBuff = 281844; + public const uint WarriorIgnorePain = 190456; +} + +[Script] +class spell_azerite_gen_aura_calc_from_2nd_effect_triggered_spell : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)) && ValidateSpellInfo(spellInfo.GetEffect(1).TriggerSpell); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit caster = GetCaster(); - if (caster != null) - { - amount = 0; - canBeRecalculated = false; - foreach (var (_, aurApp) in caster.GetAppliedAuras().Where(pair => pair.Key == GetEffectInfo(1).TriggerSpell)) - if (aurApp.HasEffect(0)) - amount += aurApp.GetBase().GetEffect(0).GetAmount(); - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModRating)); - } + return ValidateSpellEffect((spellInfo.Id, 1)) && ValidateSpellInfo(spellInfo.GetEffect(1).TriggerSpell); } - [Script] // 270658 - Azerite Fortification - class spell_item_azerite_fortification : AuraScript + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) { - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + Unit caster = GetCaster(); + if (caster != null) { - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell == null) - return false; - - return procSpell.GetSpellInfo().HasAura(AuraType.ModStun) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2) - || procSpell.GetSpellInfo().HasEffect(SpellEffectName.KnockBack); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 271548 - Strength in Numbers - class spell_item_strength_in_numbers : SpellScript - { - const uint SpellStrengthInNumbersTrait = 271546; - const uint SpellStrengthInNumbersBuff = 271550; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellStrengthInNumbersTrait, SpellStrengthInNumbersBuff); - } - - void TriggerHealthBuff() - { - AuraEffect trait = GetCaster().GetAuraEffect(SpellStrengthInNumbersTrait, 0, GetCaster().GetGUID()); - if (trait != null) - { - long enemies = GetUnitTargetCountForEffect(0); - if (enemies != 0) - GetCaster().CastSpell(GetCaster(), SpellStrengthInNumbersBuff, new CastSpellExtraArgs(TriggerCastFlags.FullMask) - .AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount()) - .AddSpellMod(SpellValueMod.AuraStack, (int)enemies)); - } - } - - public override void Register() - { - AfterHit.Add(new(TriggerHealthBuff)); - } - } - - [Script] // 271843 - Blessed Portents - class spell_item_blessed_portents : AuraScript - { - const uint SpellBlessedPortentsTrait = 267889; - const uint SpellBlessedPortentsHeal = 280052; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellBlessedPortentsTrait, SpellBlessedPortentsHeal); - } - - void CheckProc(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - if (GetTarget().HealthBelowPctDamaged(50, dmgInfo.GetDamage())) - { - Unit caster = GetCaster(); - if (caster != null) - { - AuraEffect trait = caster.GetAuraEffect(SpellBlessedPortentsTrait, 0, caster.GetGUID()); - if (trait != null) - caster.CastSpell(GetTarget(), SpellBlessedPortentsHeal, new CastSpellExtraArgs(TriggerCastFlags.FullMask) - .AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount())); - } - } - else - PreventDefaultAction(); - } - - public override void Register() - { - OnEffectAbsorb.Add(new(CheckProc, 0)); - } - } - - [Script] // 272260 - Concentrated Mending - class spell_item_concentrated_mending : AuraScript - { - const uint SpellConcentratedMendingTrait = 267882; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellConcentratedMendingTrait); - } - - void RecalculateHealAmount(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster != null) - { - AuraEffect trait = caster.GetAuraEffect(SpellConcentratedMendingTrait, 0, caster.GetGUID()); - if (trait != null) - aurEff.ChangeAmount((int)(trait.GetAmount() * aurEff.GetTickNumber())); - } - } - - public override void Register() - { - OnEffectUpdatePeriodic.Add(new(RecalculateHealAmount, 0, AuraType.PeriodicHeal)); - } - } - - [Script] // 272276 - Bracing Chill - class spell_item_bracing_chill_proc : AuraScript - { - const uint SpellBracingChillTrait = 267884; - const uint SpellBracingChillHeal = 272428; - const uint SpellBracingChillSearchJumpTarget = 272436; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellBracingChillTrait, SpellBracingChillHeal, SpellBracingChillSearchJumpTarget); - } - - bool CheckHealCaster(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return GetCasterGUID() == eventInfo.GetActor().GetGUID(); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Unit caster = procInfo.GetActor(); - if (caster == null) - return; - - AuraEffect trait = caster.GetAuraEffect(SpellBracingChillTrait, 0, caster.GetGUID()); - if (trait != null) - caster.CastSpell(procInfo.GetProcTarget(), SpellBracingChillHeal, - new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount())); - - if (GetStackAmount() > 1) - caster.CastSpell(null, SpellBracingChillSearchJumpTarget, - new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, GetStackAmount() - 1)); - - Remove(); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckHealCaster, 0, AuraType.Dummy)); - AfterEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 272436 - Bracing Chill - class spell_item_bracing_chill_search_jump_target : SpellScript - { - const uint SpellBracingChill = 272276; - - void FilterTarget(List targets) - { - if (targets.Empty()) - return; - - List copy = new(targets); - copy.RandomResize(target => target.IsUnit() && !target.ToUnit().HasAura(SpellBracingChill, GetCaster().GetGUID()), 1); - - if (!copy.Empty()) - { - // found a preferred target, use that - targets = copy; - return; - } - - WorldObject target = targets.SelectRandom(); - targets.Clear(); - targets.Add(target); - } - - void MoveAura(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellBracingChill, - new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, GetSpellValue().AuraStackAmount)); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTarget, 0, Targets.UnitDestAreaAlly)); - OnEffectHitTarget.Add(new(MoveAura, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 272837 - Trample the Weak - class spell_item_trample_the_weak : AuraScript - { - bool CheckHealthPct(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetActor().GetHealthPct() > eventInfo.GetActionTarget().GetHealthPct(); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckHealthPct, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 272892 - Wracking Brilliance - class spell_item_wracking_brilliance : AuraScript - { - const uint SpellAgonySoulShardGain = 210067; - - bool _canTrigger = true; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellAgonySoulShardGain); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null) - return false; - - if (spellInfo.Id != SpellAgonySoulShardGain) - return false; - - _canTrigger = !_canTrigger; // every other soul shard gain - return _canTrigger; - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 275514 - Orbital Precision - class spell_item_orbital_precision : AuraScript - { - const uint SpellMageFrozenOrb = 84714; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellMageFrozenOrb); - } - - bool CheckFrozenOrbActive(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetActor().GetAreaTrigger(SpellMageFrozenOrb) != null; - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckFrozenOrbActive, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 277966 - Blur of Talons - class spell_item_blur_of_talons : AuraScript - { - const uint SpellHunterCoordinatedAssault = 266779; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellHunterCoordinatedAssault); - } - - bool CheckCoordinatedAssaultActive(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetActor().HasAura(SpellHunterCoordinatedAssault, eventInfo.GetActor().GetGUID()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckCoordinatedAssaultActive, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 278519 - Divine Right - class spell_item_divine_right : AuraScript - { - bool CheckHealthPct(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget().HasAuraState(AuraStateType.Wounded20Percent, eventInfo.GetSpellInfo(), eventInfo.GetActor()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckHealthPct, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 280409 - Blood Rite - class spell_item_blood_rite : AuraScript - { - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - RefreshDuration(); - } - - public override void Register() - { - AfterEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - } - - [Script] // 281843 - Tradewinds - class spell_item_tradewinds : AuraScript - { - const uint SpellTradewindsAllyBuff = 281844; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellTradewindsAllyBuff); - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - AuraEffect trait = GetTarget().GetAuraEffect(GetEffectInfo(1).TriggerSpell, 1); - if (trait != null) - GetTarget().CastSpell(null, SpellTradewindsAllyBuff, - new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount())); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.ModRating, AuraEffectHandleModes.Real)); - } - } - - [Script] // 287379 - Bastion of Might - class spell_item_bastion_of_might : SpellScript - { - const uint SpellWarriorIgnorePain = 190456; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellWarriorIgnorePain); - } - - void TriggerIgnorePain() - { - GetCaster().CastSpell(GetCaster(), SpellWarriorIgnorePain, GetSpell()); - } - - public override void Register() - { - AfterHit.Add(new(TriggerIgnorePain)); - } - } - - [Script] // 287650 - Echoing Blades - class spell_item_echoing_blades : AuraScript - { - ObjectGuid _lastFanOfKnives; - - void PrepareProc(ProcEventInfo eventInfo) - { - if (eventInfo.GetProcSpell() != null) - { - if (eventInfo.GetProcSpell().m_castId != _lastFanOfKnives) - GetEffect(0).RecalculateAmount(); - - _lastFanOfKnives = eventInfo.GetProcSpell().m_castId; - } - } - - bool CheckFanOfKnivesCounter(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return aurEff.GetAmount() > 0; - } - - void ReduceCounter(AuraEffect aurEff, ProcEventInfo procInfo) - { - aurEff.SetAmount(aurEff.GetAmount() - 1); - } - - public override void Register() - { - DoPrepareProc.Add(new(PrepareProc)); - DoCheckEffectProc.Add(new(CheckFanOfKnivesCounter, 0, AuraType.ProcTriggerSpell)); - AfterEffectProc.Add(new(ReduceCounter, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 287653 - Echoing Blades - class spell_item_echoing_blades_damage : SpellScript - { - const uint SpellEchoingBladesTrait = 287649; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellEchoingBladesTrait, 2)); - } - - void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - AuraEffect trait = GetCaster().GetAuraEffect(SpellEchoingBladesTrait, 2); - if (trait != null) - damage = trait.GetAmount() * 2; - } - - void ForceCritical(Unit victim, ref float critChance) - { - critChance = 100.0f; - } - - public override void Register() - { - CalcDamage.Add(new(CalculateDamage)); - OnCalcCritChance.Add(new(ForceCritical)); - } - } - - [Script] // 288882 - Hour of Reaping - class spell_item_hour_of_reaping : AuraScript - { - const uint SpellDhSoulBarrier = 263648; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDhSoulBarrier); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return GetStackAmount() == GetAura().CalcMaxStackAmount(); - } - - void TriggerSoulBarrier(AuraEffect aurEff, ProcEventInfo procInfo) - { - GetTarget().CastSpell(GetTarget(), SpellDhSoulBarrier, new CastSpellExtraArgs(aurEff)); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - AfterEffectProc.Add(new(TriggerSoulBarrier, 0, AuraType.Dummy)); - } - } - - [Script] // 304086 - Azerite Fortification - class spell_item_conflict_wearer_on_stun_proc : AuraScript - { - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell == null) - return false; - - return procSpell.GetSpellInfo().HasAura(AuraType.ModStun) - || procSpell.GetSpellInfo().HasAura(AuraType.ModStunDisableGravity); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 305723 - Strife (Azerite Essence) - class spell_item_conflict_rank3 : AuraScript - { - bool CheckProc(ProcEventInfo eventInfo) - { - if (eventInfo.GetHitMask().HasAnyFlag(ProcFlagsHit.Interrupt | ProcFlagsHit.Dispel)) - return true; - - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell == null) - return false; - - bool isCrowdControl = procSpell.GetSpellInfo().HasAura(AuraType.ModConfuse) - || procSpell.GetSpellInfo().HasAura(AuraType.ModFear) - || procSpell.GetSpellInfo().HasAura(AuraType.ModStun) - || procSpell.GetSpellInfo().HasAura(AuraType.ModPacify) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) - || procSpell.GetSpellInfo().HasAura(AuraType.ModSilence) - || procSpell.GetSpellInfo().HasAura(AuraType.ModPacifySilence) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2); - - if (!isCrowdControl) - return false; - - return eventInfo.GetActionTarget().HasAura(aura => aura.GetCastId() == procSpell.m_castId); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } - } - - [Script] // 277253 - Heart of Azeroth - class spell_item_heart_of_azeroth : AuraScript - { - void SetEquippedFlag(AuraEffect effect, AuraEffectHandleModes mode) - { - SetState(true); - } - - void ClearEquippedFlag(AuraEffect effect, AuraEffectHandleModes mode) - { - SetState(false); - } - - void SetState(bool equipped) - { - Player target = GetTarget().ToPlayer(); - if (target != null) - { - target.ApplyAllAzeriteEmpoweredItemMods(equipped); - - PlayerAzeriteItemEquippedStatusChanged statusChanged = new(); - statusChanged.IsHeartEquipped = equipped; - target.SendPacket(statusChanged); - } - } - - public override void Register() - { - OnEffectApply.Add(new(SetEquippedFlag, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(ClearEquippedFlag, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 315176 - Grasping Tendrils - class spell_item_corruption_grasping_tendrils : AuraScript - { - public override bool Load() - { - return GetUnitOwner().IsPlayer(); - } - - void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player player = GetUnitOwner().ToPlayer(); - amount = (int)MathFunctions.Clamp(10.0f + player.GetRatingBonusValue(CombatRating.Corruption) - player.GetRatingBonusValue(CombatRating.CorruptionResistance), 0.0f, 99.0f); + amount = 0; canBeRecalculated = false; + foreach (var aurApp in caster.GetAppliedAuras(GetEffectInfo(1).TriggerSpell)) + if (aurApp.HasEffect(0)) + amount += aurApp.GetBase().GetEffect(0).GetAmount(); + } + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModRating)); + } +} + +[Script] // 270658 - Azerite Fortification +class spell_item_azerite_fortification : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + return procSpell.GetSpellInfo().HasAura(AuraType.ModStun) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2) + || procSpell.GetSpellInfo().HasEffect(SpellEffectName.KnockBack); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 271548 - Strength in Numbers +class spell_item_strength_in_numbers : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StrengthInNumbersTrait, SpellIds.StrengthInNumbersBuff); + } + + void TriggerHealthBuff() + { + AuraEffect trait = GetCaster().GetAuraEffect(SpellIds.StrengthInNumbersTrait, 0, GetCaster().GetGUID()); + if (trait != null) + { + long enemies = GetUnitTargetCountForEffect(0); + if (enemies != 0) + GetCaster().CastSpell(GetCaster(), SpellIds.StrengthInNumbersBuff, new CastSpellExtraArgs(TriggerCastFlags.FullMask) + .AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount()) + .AddSpellMod(SpellValueMod.AuraStack, (int)enemies)); + } + } + + public override void Register() + { + AfterHit.Add(new(TriggerHealthBuff)); + } +} + +[Script] // 271843 - Blessed Portents +class spell_item_blessed_portents : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlessedPortentsTrait, SpellIds.BlessedPortentsHeal); + } + + void CheckProc(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + if (GetTarget().HealthBelowPctDamaged(50, dmgInfo.GetDamage())) + { + Unit caster = GetCaster(); + if (caster != null) + { + AuraEffect trait = caster.GetAuraEffect(SpellIds.BlessedPortentsTrait, 0, caster.GetGUID()); + if (trait != null) + caster.CastSpell(GetTarget(), SpellIds.BlessedPortentsHeal, new CastSpellExtraArgs(TriggerCastFlags.FullMask) + .AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount())); + } + } + else + PreventDefaultAction(); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(CheckProc, 0)); + } +} + +[Script] // 272260 - Concentrated Mending +class spell_item_concentrated_mending : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ConcentratedMendingTrait); + } + + void RecalculateHealAmount(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + { + AuraEffect trait = caster.GetAuraEffect(SpellIds.ConcentratedMendingTrait, 0, caster.GetGUID()); + if (trait != null) + aurEff.ChangeAmount((int)(trait.GetAmount() * aurEff.GetTickNumber())); + } + } + + public override void Register() + { + OnEffectUpdatePeriodic.Add(new(RecalculateHealAmount, 0, AuraType.PeriodicHeal)); + } +} + +[Script] // 272276 - Bracing Chill +class spell_item_bracing_chill_proc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BracingChillTrait, SpellIds.BracingChillHeal, SpellIds.BracingChillSearchJumpTarget); + } + + bool CheckHealCaster(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return GetCasterGUID() == eventInfo.GetActor().GetGUID(); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Unit caster = procInfo.GetActor(); + if (caster == null) + return; + + AuraEffect trait = caster.GetAuraEffect(SpellIds.BracingChillTrait, 0, caster.GetGUID()); + if (trait != null) + caster.CastSpell(procInfo.GetProcTarget(), SpellIds.BracingChillHeal, + new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount())); + + if (GetStackAmount() > 1) + caster.CastSpell(null, SpellIds.BracingChillSearchJumpTarget, + new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, GetStackAmount() - 1)); + + Remove(); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckHealCaster, 0, AuraType.Dummy)); + AfterEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 272436 - Bracing Chill +class spell_item_bracing_chill_search_jump_target : SpellScript +{ + void FilterTarget(List targets) + { + if (targets.Empty()) + return; + + List copy = new(targets); + copy.RandomResize(target => target.IsUnit() && !target.ToUnit().HasAura(SpellIds.BracingChill, GetCaster().GetGUID()), 1); + + if (!copy.Empty()) + { + // found a preferred target, use that + targets = copy; + return; } - public override void Register() + WorldObject target = targets.SelectRandom(); + targets.Clear(); + targets.Add(target); + } + + void MoveAura(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.BracingChill, + new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, GetSpellValue().AuraStackAmount)); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTarget, 0, Targets.UnitDestAreaAlly)); + OnEffectHitTarget.Add(new(MoveAura, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 272837 - Trample the Weak +class spell_item_trample_the_weak : AuraScript +{ + bool CheckHealthPct(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActor().GetHealthPct() > eventInfo.GetActionTarget().GetHealthPct(); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckHealthPct, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 272892 - Wracking Brilliance +class spell_item_wracking_brilliance : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AgonySoulShardGain); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null) + return false; + + if (spellInfo.Id != SpellIds.AgonySoulShardGain) + return false; + + _canTrigger = !_canTrigger; // every other soul shard gain + return _canTrigger; + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } + + bool _canTrigger = true; +} + +[Script] // 275514 - Orbital Precision +class spell_item_orbital_precision : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MageFrozenOrb); + } + + bool CheckFrozenOrbActive(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActor().GetAreaTrigger(SpellIds.MageFrozenOrb) != null; + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckFrozenOrbActive, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 277966 - Blur of Talons +class spell_item_blur_of_talons : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HunterCoordinatedAssault); + } + + bool CheckCoordinatedAssaultActive(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActor().HasAura(SpellIds.HunterCoordinatedAssault, eventInfo.GetActor().GetGUID()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckCoordinatedAssaultActive, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 278519 - Divine Right +class spell_item_divine_right : AuraScript +{ + bool CheckHealthPct(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget().HasAuraState(AuraStateType.Wounded20Percent, eventInfo.GetSpellInfo(), eventInfo.GetActor()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckHealthPct, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 280409 - Blood Rite +class spell_item_blood_rite : AuraScript +{ + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + RefreshDuration(); + } + + public override void Register() + { + AfterEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 281843 - Tradewinds +class spell_item_tradewinds : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TradewindsAllyBuff); + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + AuraEffect trait = GetTarget().GetAuraEffect(GetEffectInfo(1).TriggerSpell, 1); + if (trait != null) + GetTarget().CastSpell(null, SpellIds.TradewindsAllyBuff, + new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, trait.GetAmount())); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.ModRating, AuraEffectHandleModes.Real)); + } +} + +[Script] // 287379 - Bastion of Might +class spell_item_bastion_of_might : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.WarriorIgnorePain); + } + + void TriggerIgnorePain() + { + GetCaster().CastSpell(GetCaster(), SpellIds.WarriorIgnorePain, GetSpell()); + } + + public override void Register() + { + AfterHit.Add(new(TriggerIgnorePain)); + } +} + +[Script] // 287650 - Echoing Blades +class spell_item_echoing_blades : AuraScript +{ + ObjectGuid _lastFanOfKnives; + + void PrepareProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetProcSpell() != null) { - DoEffectCalcAmount.Add(new(CalcAmount, 0, AuraType.ModDecreaseSpeed)); + if (eventInfo.GetProcSpell().m_castId != _lastFanOfKnives) + GetEffect(0).RecalculateAmount(); + + _lastFanOfKnives = eventInfo.GetProcSpell().m_castId; } } + + bool CheckFanOfKnivesCounter(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return aurEff.GetAmount() > 0; + } + + void ReduceCounter(AuraEffect aurEff, ProcEventInfo procInfo) + { + aurEff.SetAmount(aurEff.GetAmount() - 1); + } + + public override void Register() + { + DoPrepareProc.Add(new(PrepareProc)); + DoCheckEffectProc.Add(new(CheckFanOfKnivesCounter, 0, AuraType.ProcTriggerSpell)); + AfterEffectProc.Add(new(ReduceCounter, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 287653 - Echoing Blades +class spell_item_echoing_blades_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.EchoingBladesTrait, 2)); + } + + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + AuraEffect trait = GetCaster().GetAuraEffect(SpellIds.EchoingBladesTrait, 2); + if (trait != null) + damage = trait.GetAmount() * 2; + } + + void ForceCritical(Unit victim, ref float critChance) + { + critChance = 100.0f; + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamage)); + OnCalcCritChance.Add(new(ForceCritical)); + } +} + +[Script] // 288882 - Hour of Reaping +class spell_item_hour_of_reaping : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DhSoulBarrier); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return GetStackAmount() == GetAura().CalcMaxStackAmount(); + } + + void TriggerSoulBarrier(AuraEffect aurEff, ProcEventInfo procInfo) + { + GetTarget().CastSpell(GetTarget(), SpellIds.DhSoulBarrier, aurEff); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + AfterEffectProc.Add(new(TriggerSoulBarrier, 0, AuraType.Dummy)); + } +} + +[Script] // 304086 - Azerite Fortification +class spell_item_conflict_wearer_on_stun_proc : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + return procSpell.GetSpellInfo().HasAura(AuraType.ModStun) + || procSpell.GetSpellInfo().HasAura(AuraType.ModStunDisableGravity); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 305723 - Strife (Azerite Essence) +class spell_item_conflict_rank3 : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) + { + if ((eventInfo.GetHitMask() & (ProcFlagsHit.Interrupt | ProcFlagsHit.Dispel)) != 0) + return true; + + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + bool isCrowdControl = procSpell.GetSpellInfo().HasAura(AuraType.ModConfuse) + || procSpell.GetSpellInfo().HasAura(AuraType.ModFear) + || procSpell.GetSpellInfo().HasAura(AuraType.ModStun) + || procSpell.GetSpellInfo().HasAura(AuraType.ModPacify) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) + || procSpell.GetSpellInfo().HasAura(AuraType.ModSilence) + || procSpell.GetSpellInfo().HasAura(AuraType.ModPacifySilence) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2); + + if (!isCrowdControl) + return false; + + return eventInfo.GetActionTarget().HasAura(aura => aura.GetCastId() == procSpell.m_castId); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] // 277253 - Heart of Azeroth +class spell_item_heart_of_azeroth : AuraScript +{ + void SetEquippedFlag(AuraEffect effect, AuraEffectHandleModes mode) + { + SetState(true); + } + + void ClearEquippedFlag(AuraEffect effect, AuraEffectHandleModes mode) + { + SetState(false); + } + + void SetState(bool equipped) + { + Player target = GetTarget().ToPlayer(); + if (target != null) + { + target.ApplyAllAzeriteEmpoweredItemMods(equipped); + + PlayerAzeriteItemEquippedStatusChanged statusChanged = new(); + statusChanged.IsHeartEquipped = equipped; + target.SendPacket(statusChanged); + } + } + + public override void Register() + { + OnEffectApply.Add(new(SetEquippedFlag, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(ClearEquippedFlag, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 315176 - Grasping Tendrils +class spell_item_corruption_grasping_tendrils : AuraScript +{ + public override bool Load() + { + return GetUnitOwner().IsPlayer(); + } + + void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player player = GetUnitOwner().ToPlayer(); + amount = (int)Math.Clamp(10.0f + player.GetRatingBonusValue(CombatRating.Corruption) - player.GetRatingBonusValue(CombatRating.CorruptionResistance), 0.0f, 99.0f); + canBeRecalculated = false; + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalcAmount, 0, AuraType.ModDecreaseSpeed)); + } } \ No newline at end of file diff --git a/Source/Scripts/Spells/DeathKnight.cs b/Source/Scripts/Spells/DeathKnight.cs index 8e1f11fa3..8deaa0412 100644 --- a/Source/Scripts/Spells/DeathKnight.cs +++ b/Source/Scripts/Spells/DeathKnight.cs @@ -1,987 +1,1395 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Game.AI; using Game.Entities; -using Game.Networking.Packets; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; using System.Linq; -using static Global; -namespace Scripts.Spells.DeathKnight +namespace Scripts.Spells.DeathKnight; + +struct SpellIds { - struct SpellIds - { - public const uint ArmyFleshBeastTransform = 127533; - public const uint ArmyGeistTransform = 127534; - public const uint ArmyNorthrendSkeletonTransform = 127528; - public const uint ArmySkeletonTransform = 127527; - public const uint ArmySpikedGhoulTransform = 127525; - public const uint ArmySuperZombieTransform = 127526; - public const uint BlindingSleetSlow = 317898; - public const uint Blood = 137008; - public const uint BloodPlague = 55078; - public const uint BloodShieldAbsorb = 77535; - public const uint BloodShieldMastery = 77513; - public const uint BreathOfSindragosa = 152279; - public const uint CorpseExplosionTriggered = 43999; - public const uint DarkSimulacrumBuff = 77616; - public const uint DarkSimulacrumSpellpowerBuff = 94984; - public const uint DeathAndDecayDamage = 52212; - public const uint DeathCoilDamage = 47632; - public const uint DeathGripDummy = 243912; - public const uint DeathGripJump = 49575; - public const uint DeathGripTaunt = 51399; - public const uint DeathStrikeHeal = 45470; - public const uint DeathStrikeOffhand = 66188; - public const uint FesteringWound = 194310; - public const uint Frost = 137006; - public const uint FrostFever = 55095; - public const uint FrostScythe = 207230; - public const uint FrostShield = 207203; - public const uint GlyphOfFoulMenagerie = 58642; - public const uint GlyphOfTheGeist = 58640; - public const uint GlyphOfTheSkeleton = 146652; - public const uint KillingMachineProc = 51124; - public const uint MarkOfBloodHeal = 206945; - public const uint NecrosisEffect = 216974; - public const uint Obliteration = 281238; - public const uint ObliterationRuneEnergize = 281327; - public const uint PillarOfFrost = 51271; - public const uint RaiseDeadSummon = 52150; - public const uint RecentlyUsedDeathStrike = 180612; - public const uint RunicPowerEnergize = 49088; - public const uint RunicReturn = 61258; - public const uint SludgeBelcher = 207313; - public const uint SludgeBelcherSummon = 212027; - public const uint DeathStrikeEnabler = 89832; // Server Side - public const uint TighteningGrasp = 206970; - //public const uint TighteningGraspSlow = 143375; // dropped in BfA - public const uint Unholy = 137007; - public const uint UnholyGroundHaste = 374271; - public const uint UnholyGroundTalent = 374265; - public const uint UnholyVigor = 196263; - public const uint VolatileShielding = 207188; - public const uint VolatileShieldingDamage = 207194; - } + public const uint AntiMagicBarrier = 205727; + public const uint ArmyFleshBeastTransform = 127533; + public const uint ArmyGeistTransform = 127534; + public const uint ArmyNorthrendSkeletonTransform = 127528; + public const uint ArmySkeletonTransform = 127527; + public const uint ArmySpikedGhoulTransform = 127525; + public const uint ArmySuperZombieTransform = 127526; + public const uint BlindingSleetSlow = 317898; + public const uint Blood = 137008; + public const uint BlooddrinkerDebuff = 458687; + public const uint BloodPlague = 55078; + public const uint BloodShieldAbsorb = 77535; + public const uint BloodShieldMastery = 77513; + public const uint BoneShield = 195181; + public const uint BreathOfSindragosa = 152279; + public const uint BrittleDebuff = 374557; + public const uint CleavingStrikes = 316916; + public const uint CorpseExplosionTriggered = 43999; + public const uint CrimsonScourgeBuff = 81141; + public const uint DarkSimulacrumBuff = 77616; + public const uint DarkSimulacrumSpellpowerBuff = 94984; + public const uint DeathAndDecay = 43265; + public const uint DeathAndDecayDamage = 52212; + public const uint DeathAndDecayIncreaseTargets = 188290; + public const uint DeathCoilDamage = 47632; + public const uint DeathGripDummy = 243912; + public const uint DeathGripJump = 49575; + public const uint DeathGripTaunt = 51399; + public const uint DeathStrikeEnabler = 89832; // Server Side + public const uint DeathStrikeHeal = 45470; + public const uint DeathStrikeOffhand = 66188; + public const uint FesteringWound = 194310; + public const uint Frost = 137006; + public const uint FrostFever = 55095; + public const uint FrostScythe = 207230; + public const uint FrostShield = 207203; + public const uint GlyphOfFoulMenagerie = 58642; + public const uint GlyphOfTheGeist = 58640; + public const uint GlyphOfTheSkeleton = 146652; + public const uint GorefiendsGrasp = 108199; + public const uint HeartbreakerEnergize = 210738; + public const uint HeartbreakerTalent = 221536; + public const uint IcePrisonRoot = 454787; + public const uint IcePrisonTalent = 454786; + public const uint KillingMachineProc = 51124; + public const uint MarkOfBloodHeal = 206945; + public const uint NecrosisEffect = 216974; + public const uint Obliteration = 281238; + public const uint ObliterationRuneEnergize = 281327; + public const uint PillarOfFrost = 51271; + public const uint RaiseDeadSummon = 52150; + public const uint ReaperOfSoulsProc = 469172; + public const uint RecentlyUsedDeathStrike = 180612; + public const uint RunicCorruption = 51460; + public const uint RunicPowerEnergize = 49088; + public const uint RunicReturn = 61258; + public const uint SanguineGroundTalent = 391458; + public const uint SanguineGround = 391459; + public const uint SludgeBelcher = 207313; + public const uint SludgeBelcherSummon = 212027; + public const uint SmotheringOffense = 435005; + public const uint SoulReaper = 343294; + public const uint SoulReaperDamage = 343295; + public const uint SubduingGraspDebuff = 454824; + public const uint SubduingGraspTalent = 454822; + public const uint Unholy = 137007; + public const uint UnholyVigor = 196263; + public const uint DhVoraciousLeech = 274009; + public const uint DhVoraciousTalent = 273953; +} - [Script] // 70656 - Advantage (T10 4P Melee Bonus) - class spell_dk_advantage_t10_4p : AuraScript +[Script] // 70656 - Advantage (T10 4P Melee Bonus) +class spell_dk_advantage_t10_4p : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) { - bool CheckProc(ProcEventInfo eventInfo) + Unit caster = eventInfo.GetActor(); + if (caster != null) { - Unit caster = eventInfo.GetActor(); - if (caster != null) - { - Player player = caster.ToPlayer(); - if (player == null || caster.GetClass() != Class.Deathknight) + Player player = caster.ToPlayer(); + if (player == null || caster.GetClass() != Class.DeathKnight) + return false; + + for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) + if (player.GetRuneCooldown(i) == 0) return false; - for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) - if (player.GetRuneCooldown(i) == 0) - return false; + return true; + } - return true; - } + return false; + } + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] // 48707 - Anti-Magic Shell +class spell_dk_anti_magic_shell : AuraScript +{ + int absorbPct; + int maxHealth; + uint absorbedAmount; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RunicPowerEnergize) + && ValidateSpellEffect((spellInfo.Id, 1), (SpellIds.AntiMagicBarrier, 2)); + } + + public override bool Load() + { + absorbPct = GetEffectInfo(1).CalcValue(GetCaster()); + maxHealth = (int)GetCaster().GetMaxHealth(); + absorbedAmount = 0; + return true; + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + amount = MathFunctions.CalculatePct(maxHealth, absorbPct); + AuraEffect antiMagicBarrier = GetCaster().GetAuraEffect(SpellIds.AntiMagicBarrier, 2); + if (antiMagicBarrier != null) + + MathFunctions.AddPct(ref amount, antiMagicBarrier.GetAmount()); + Player player = GetUnitOwner().ToPlayer(); + if (player != null) + MathFunctions.AddPct(ref amount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone) + player.GetTotalAuraModifier(AuraType.ModVersatility)); + } + + void Trigger(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + absorbedAmount += absorbAmount; + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(absorbAmount, 2 * absorbAmount * 100 / maxHealth)); + GetTarget().CastSpell(GetTarget(), SpellIds.RunicPowerEnergize, args); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + AfterEffectAbsorb.Add(new(Trigger, 0)); + } +} + +// 195182 - Marrowrend +// 195292 - Death's Caress +[Script("spell_dk_marrowrend_apply_bone_shield", 2)] +[Script("spell_dk_deaths_caress_apply_bone_shield", 2)] +class spell_dk_apply_bone_shield : SpellScript +{ + uint _effIndex; + + public spell_dk_apply_bone_shield(uint effIndex) + { + _effIndex = effIndex; + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BoneShield) + && ValidateSpellEffect((spellInfo.Id, _effIndex)) + && spellInfo.GetEffect(_effIndex).CalcBaseValue(null, null, 0, 0) <= (int)Global.SpellMgr.GetSpellInfo(SpellIds.BoneShield, Difficulty.None).StackAmount; + } + + void HandleHitTarget(uint effIndex) + { + Unit caster = GetCaster(); + for (int i = 0; i < GetEffectValue(); ++i) + caster.CastSpell(caster, SpellIds.BoneShield, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleHitTarget, _effIndex, SpellEffectName.Dummy)); + } +} + +// 127517 - Army Transform +[Script] // 6.x, does this belong here or in spell_generic? where do we cast this? sniffs say this is only cast when caster has glyph of foul menagerie. +class spell_dk_army_transform : SpellScript +{ + static uint[] ArmyTransforms = + { + SpellIds.ArmyFleshBeastTransform, + SpellIds.ArmyGeistTransform, + SpellIds.ArmyNorthrendSkeletonTransform, + SpellIds.ArmySkeletonTransform, + SpellIds.ArmySpikedGhoulTransform, + SpellIds.ArmySuperZombieTransform, + }; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlyphOfFoulMenagerie); + } + + public override bool Load() + { + return GetCaster().IsGuardian(); + } + + SpellCastResult CheckCast() + { + Unit owner = GetCaster().GetOwner(); + if (owner != null) + if (owner.HasAura(SpellIds.GlyphOfFoulMenagerie)) + return SpellCastResult.SpellCastOk; + + return SpellCastResult.SpellUnavailable; + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), ArmyTransforms.SelectRandom(), true); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 207167 - Blinding Sleet +class spell_dk_blinding_sleet : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlindingSleetSlow); + } + + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) + GetTarget().CastSpell(GetTarget(), SpellIds.BlindingSleetSlow, true); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.ModConfuse, AuraEffectHandleModes.Real)); + } +} + +[Script] // 206931 - Blooddrinker +class spell_dk_blooddrinker : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlooddrinkerDebuff); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.BlooddrinkerDebuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.PeriodicLeech, AuraEffectHandleModes.Real)); + } +} + +[Script] // 50842 - Blood Boil +class spell_dk_blood_boil : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BloodPlague); + } + + void HandleEffect() + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.BloodPlague, true); + } + + public override void Register() + { + OnHit.Add(new(HandleEffect)); + } +} + +[Script] // 374504 - Brittle +class spell_dk_brittle : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BrittleDebuff); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(eventInfo.GetActionTarget(), SpellIds.BrittleDebuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 81136 - Crimson Scourge +class spell_dk_crimson_scourge : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BloodPlague, SpellIds.CrimsonScourgeBuff, SpellIds.DeathAndDecay); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + return procInfo.GetProcTarget().HasAura(SpellIds.BloodPlague, procInfo.GetActor().GetGUID()); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit actor = eventInfo.GetActor(); + actor.GetSpellHistory().RestoreCharge(Global.SpellMgr.GetSpellInfo(SpellIds.DeathAndDecay, Difficulty.None).ChargeCategoryId); + actor.CastSpell(actor, SpellIds.CrimsonScourgeBuff, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// 49028 - Dancing Rune Weapon +[Script] // 7.1.5 +class spell_dk_dancing_rune_weapon : AuraScript +{ + const uint NpcDkDancingRuneWeapon = 27893; + + public override bool Validate(SpellInfo spellInfo) + { + if (Global.ObjectMgr.GetCreatureTemplate(NpcDkDancingRuneWeapon) == null) return false; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } + return true; } - [Script] // 48707 - Anti-Magic Shell - class spell_dk_anti_magic_shell : AuraScript + // This is a port of the old switch hack in Unit.cpp, it's not correct + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - int absorbPct; - ulong maxHealth; - uint absorbedAmount; + PreventDefaultAction(); + Unit caster = GetCaster(); + if (caster == null) + return; - public spell_dk_anti_magic_shell() + Unit drw = null; + foreach (Unit controlled in caster.m_Controlled) { - absorbPct = 0; - maxHealth = 0; - absorbedAmount = 0; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RunicPowerEnergize, SpellIds.VolatileShielding) - && ValidateSpellEffect((spellInfo.Id, 1)); - } - - public override bool Load() - { - absorbPct = GetEffectInfo(1).CalcValue(GetCaster()); - maxHealth = GetCaster().GetMaxHealth(); - absorbedAmount = 0; - return true; - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - amount = (int)MathFunctions.CalculatePct(maxHealth, absorbPct); - - Player player = GetUnitOwner().ToPlayer(); - if (player != null) - MathFunctions.AddPct(ref amount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone) + player.GetTotalAuraModifier(AuraType.ModVersatility)); - } - - void Trigger(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - absorbedAmount += absorbAmount; - - if (!GetTarget().HasAura(SpellIds.VolatileShielding)) + if (controlled.GetEntry() == NpcDkDancingRuneWeapon) { - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(absorbAmount, 2 * absorbAmount * 100 / maxHealth)); - GetTarget().CastSpell(GetTarget(), SpellIds.RunicPowerEnergize, args); + drw = controlled; + break; } } - void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + if (drw == null || drw.GetVictim() == null) + return; + + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null) + return; + + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + int amount = (int)(damageInfo.GetDamage()) / 2; + SpellNonMeleeDamage log = new(drw, drw.GetVictim(), spellInfo, new(spellInfo.GetSpellXSpellVisualId(drw), 0), spellInfo.GetSchoolMask()); + log.damage = (uint)amount; + Unit.DealDamage(drw, drw.GetVictim(), (uint)amount, null, DamageEffectType.Direct, spellInfo.GetSchoolMask(), spellInfo, true); + drw.SendSpellNonMeleeDamageLog(log); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 77606 - Dark Simulacrum +class spell_dk_dark_simulacrum : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DarkSimulacrumBuff, SpellIds.DarkSimulacrumSpellpowerBuff); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + if (!GetTarget().IsPlayer()) + return procSpell.GetSpellInfo().HasAttribute(SpellAttr9.AllowDarkSimulacrum); + + if (!procSpell.HasPowerTypeCost(PowerType.Mana)) + return false; + + // filter out spells not castable by mind controlled players (teleports, summons, item creations (healthstones)) + if (procSpell.GetSpellInfo().HasAttribute(SpellAttr1.NoAutocastAi)) + return false; + + return true; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + caster.CastSpell(caster, SpellIds.DarkSimulacrumBuff, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(eventInfo.GetProcSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, (int)eventInfo.GetSpellInfo().Id)); + + caster.CastSpell(caster, SpellIds.DarkSimulacrumSpellpowerBuff, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(eventInfo.GetProcSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, GetTarget().SpellBaseDamageBonusDone(SpellSchoolMask.Magic)) + .AddSpellMod(SpellValueMod.BasePoint1, (int)GetTarget().SpellBaseHealingBonusDone(SpellSchoolMask.Magic))); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 77616 - Dark Simulacrum +class spell_dk_dark_simulacrum_buff : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return aurEff.GetAmount() == eventInfo.GetSpellInfo().Id; + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.OverrideActionbarSpellsTriggered)); + } +} + +[Script] // 43265 - Death and Decay (Aura) +class spell_dk_death_and_decay : AuraScript +{ + void HandleDummyTick(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.DeathAndDecayDamage, aurEff); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleDummyTick, 2, AuraType.PeriodicDummy)); + } +} + +[Script] // 47541 - Death Coil +class spell_dk_death_coil : SpellScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.DeathCoilDamage, SpellIds.Unholy, SpellIds.UnholyVigor); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + caster.CastSpell(GetHitUnit(), SpellIds.DeathCoilDamage, true); + AuraEffect unholyAura = caster.GetAuraEffect(SpellIds.Unholy, 6); + if (unholyAura != null) // can be any effect, just here to send SpellCastResult.DontReport on failure + caster.CastSpell(caster, SpellIds.UnholyVigor, unholyAura); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 52751 - Death Gate +class spell_dk_death_gate : SpellScript +{ + SpellCastResult CheckClass() + { + if (GetCaster().GetClass() != Class.DeathKnight) { - AuraEffect volatileShielding = GetTarget().GetAuraEffect(SpellIds.VolatileShielding, 1); - if (volatileShielding != null) + SetCustomCastResultMessage(SpellCustomErrors.MustBeDeathKnight); + return SpellCastResult.CustomError; + } + + return SpellCastResult.SpellCastOk; + } + + void HandleScript(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + Unit target = GetHitUnit(); + if (target != null) + target.CastSpell(target, (uint)GetEffectValue(), false); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckClass)); + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 49576 - Death Grip Initial +class spell_dk_death_grip_initial : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DeathGripDummy, SpellIds.DeathGripJump, SpellIds.Blood, SpellIds.DeathGripTaunt); + } + + SpellCastResult CheckCast() + { + Unit caster = GetCaster(); + // Death Grip should not be castable while jumping/falling + if (caster.HasUnitState(UnitState.Jumping) || caster.HasUnitMovementFlag(MovementFlag.Falling)) + return SpellCastResult.Moving; + + return SpellCastResult.SpellCastOk; + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.DeathGripDummy, true); + GetHitUnit().CastSpell(GetCaster(), SpellIds.DeathGripJump, true); + if (GetCaster().HasAura(SpellIds.Blood)) + GetCaster().CastSpell(GetHitUnit(), SpellIds.DeathGripTaunt, true); + } + + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 48743 - Death Pact +class spell_dk_death_pact : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 2)); + } + + void HandleCalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Unit caster = GetCaster(); + if (caster != null) + amount = (int)caster.CountPctFromMaxHealth(GetEffectInfo(2).CalcValue(caster)); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(HandleCalcAmount, 1, AuraType.SchoolHealAbsorb)); + } +} + +[Script] // 49998 - Death Strike +class spell_dk_death_strike : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DeathStrikeEnabler, SpellIds.DeathStrikeHeal, SpellIds.BloodShieldMastery, SpellIds.BloodShieldAbsorb, SpellIds.Frost, SpellIds.DeathStrikeOffhand) + && ValidateSpellEffect((spellInfo.Id, 2)); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + AuraEffect enabler = caster.GetAuraEffect(SpellIds.DeathStrikeEnabler, 0, GetCaster().GetGUID()); + if (enabler != null) + { + // Heals you for 25% of all damage taken in the last 5 sec, + int heal = MathFunctions.CalculatePct(enabler.CalculateAmount(GetCaster()), GetEffectInfo(1).CalcValue(GetCaster())); + // minimum 7.0% of maximum health. + int pctOfMaxHealth = MathFunctions.CalculatePct(GetEffectInfo(2).CalcValue(GetCaster()), caster.GetMaxHealth()); + heal = Math.Max(heal, pctOfMaxHealth); + + caster.CastSpell(caster, SpellIds.DeathStrikeHeal, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, heal)); + + AuraEffect aurEff = caster.GetAuraEffect(SpellIds.BloodShieldMastery, 0); + if (aurEff != null) + caster.CastSpell(caster, SpellIds.BloodShieldAbsorb, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, MathFunctions.CalculatePct(heal, aurEff.GetAmount()))); + + if (caster.HasAura(SpellIds.Frost)) + caster.CastSpell(GetHitUnit(), SpellIds.DeathStrikeOffhand, true); + } + } + + void TriggerRecentlyUsedDeathStrike() + { + GetCaster().CastSpell(GetCaster(), SpellIds.RecentlyUsedDeathStrike, true); + } + + public override void Register() + { + OnEffectLaunch.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); + AfterCast.Add(new(TriggerRecentlyUsedDeathStrike)); + } +} + +[Script] // 89832 - Death Strike Enabler - SpellDeathStrikeEnabler +class spell_dk_death_strike_enabler : AuraScript +{ + // Amount of seconds we calculate damage over + static byte LastSeconds = 5; + + uint[] _damagePerSecond = new uint[LastSeconds]; + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo() != null; + } + + void Update(AuraEffect aurEff) + { + // Move backwards all datas by one from [23][0][0][0][0] . [0][23][0][0][0] + _damagePerSecond = Enumerable.Range(1, _damagePerSecond.Length).Select(i => _damagePerSecond[i % _damagePerSecond.Length]).ToArray(); + _damagePerSecond[0] = 0; + } + + void HandleCalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = true; + amount = (int)_damagePerSecond.Aggregate(0u, (a, b) => a += b); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + _damagePerSecond[0] += eventInfo.GetDamageInfo().GetDamage(); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.PeriodicDummy)); + DoEffectCalcAmount.Add(new(HandleCalcAmount, 0, AuraType.PeriodicDummy)); + OnEffectUpdatePeriodic.Add(new(Update, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 85948 - Festering Strike +class spell_dk_festering_strike : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FesteringWound); + } + + void HandleScriptEffect(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.FesteringWound, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, GetEffectValue())); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.Dummy)); + } +} + +[Script] // 195621 - Frost Fever +class spell_dk_frost_fever_proc : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 47496 - Explode, Ghoul spell for Corpse Explosion +class spell_dk_ghoul_explode : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CorpseExplosionTriggered) && ValidateSpellEffect((spellInfo.Id, 2)); + } + + void HandleDamage(uint effIndex) + { + SetHitDamage((int)GetCaster().CountPctFromMaxHealth(GetEffectInfo(2).CalcValue(GetCaster()))); + } + + void Suicide(uint effIndex) + { + Unit unitTarget = GetHitUnit(); + if (unitTarget != null) + { + // Corpse Explosion (Suicide) + unitTarget.CastSpell(unitTarget, SpellIds.CorpseExplosionTriggered, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDamage, 0, SpellEffectName.SchoolDamage)); + OnEffectHitTarget.Add(new(Suicide, 1, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 69961 - Glyph of Scourge Strike +class spell_dk_glyph_of_scourge_strike_script : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + var mPeriodic = target.GetAuraEffectsByType(AuraType.PeriodicDamage); + foreach (var aurEff in mPeriodic) + { + SpellInfo spellInfo = aurEff.GetSpellInfo(); + // search our Blood Plague and Frost Fever on target + if (spellInfo.SpellFamilyName == SpellFamilyNames.Deathknight && (spellInfo.SpellFamilyFlags[2] & 0x2) != 0 && aurEff.GetCasterGUID() == caster.GetGUID()) { - CastSpellExtraArgs args = new(volatileShielding); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(absorbedAmount, volatileShielding.GetAmount())); - GetTarget().CastSpell(null, SpellIds.VolatileShieldingDamage, args); - } - } + int countMin = aurEff.GetBase().GetMaxDuration(); + int countMax = spellInfo.GetMaxDuration(); - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); - AfterEffectAbsorb.Add(new(Trigger, 0)); - AfterEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.Real)); - } - } + // this Glyph + countMax += 9000; - // 127517 - Army Transform - [Script] /// 6.x, does this belong here or in spell_generic? where do we cast this? sniffs say this is only cast when caster has glyph of foul menagerie. - class spell_dk_army_transform : SpellScript - { - uint[] ArmyTransforms = - { - SpellIds.ArmyFleshBeastTransform, - SpellIds.ArmyGeistTransform, - SpellIds. ArmyNorthrendSkeletonTransform, - SpellIds.ArmySkeletonTransform, - SpellIds.ArmySpikedGhoulTransform, - SpellIds. ArmySuperZombieTransform, - }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlyphOfFoulMenagerie); - } - - public override bool Load() - { - return GetCaster().IsGuardian(); - } - - SpellCastResult CheckCast() - { - Unit owner = GetCaster().GetOwner(); - if (owner != null) - if (owner.HasAura(SpellIds.GlyphOfFoulMenagerie)) - return SpellCastResult.SpellCastOk; - - return SpellCastResult.SpellUnavailable; - } - - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), ArmyTransforms.SelectRandom(), true); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 207167 - Blinding Sleet - class spell_dk_blinding_sleet : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlindingSleetSlow); - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) - GetTarget().CastSpell(GetTarget(), SpellIds.BlindingSleetSlow, true); - } - - public override void Register() - { - AfterEffectRemove.Add(new EffectApplyHandler(HandleOnRemove, 0, AuraType.ModConfuse, AuraEffectHandleModes.Real)); - } - } - - [Script] // 50842 - Blood Boil - class spell_dk_blood_boil : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BloodPlague); - } - - void HandleEffect() - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.BloodPlague, true); - } - - public override void Register() - { - OnHit.Add(new(HandleEffect)); - } - } - - // 49028 - Dancing Rune Weapon - [Script] /// 7.1.5 - class spell_dk_dancing_rune_weapon : AuraScript - { - const uint NpcDkDancingRuneWeapon = 27893; - - public override bool Validate(SpellInfo spellInfo) - { - if (ObjectMgr.GetCreatureTemplate(NpcDkDancingRuneWeapon) == null) - return false; - return true; - } - - // This is a port of the old switch hack in Unit.cpp, it's not correct - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = GetCaster(); - if (caster == null) - return; - - Unit drw = null; - foreach (Unit controlled in caster.m_Controlled) - { - if (controlled.GetEntry() == NpcDkDancingRuneWeapon) + if (countMin < countMax) { - drw = controlled; - break; + aurEff.GetBase().SetDuration(aurEff.GetBase().GetDuration() + 3000); + aurEff.GetBase().SetMaxDuration(countMin + 3000); } } - - if (drw == null || drw.GetVictim() == null) - return; - - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null) - return; - - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; - - int amount = (int)damageInfo.GetDamage() / 2; - SpellNonMeleeDamage log = new(drw, drw.GetVictim(), spellInfo, new SpellCastVisual(spellInfo.GetSpellXSpellVisualId(drw), 0), spellInfo.GetSchoolMask()); - log.damage = (uint)amount; - Unit.DealDamage(drw, drw.GetVictim(), (uint)amount, null, DamageEffectType.SpellDirect, spellInfo.GetSchoolMask(), spellInfo, true); - drw.SendSpellNonMeleeDamageLog(log); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); } } - [Script] // 77606 - Dark Simulacrum - class spell_dk_dark_simulacrum : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DarkSimulacrumBuff, SpellIds.DarkSimulacrumSpellpowerBuff); - } + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell == null) - return false; - - if (!GetTarget().IsPlayer()) - return procSpell.GetSpellInfo().HasAttribute(SpellAttr9.AllowDarkSimulacrum); - - if (!procSpell.HasPowerTypeCost(PowerType.Mana)) - return false; - - // filter out spells not castable by mind controlled players (teleports, summons, item creations (healthstones)) - if (procSpell.GetSpellInfo().HasAttribute(SpellAttr1.NoAutocastAi)) - return false; - - return true; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - caster.CastSpell(caster, SpellIds.DarkSimulacrumBuff, new CastSpellExtraArgs() - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(eventInfo.GetProcSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, (int)eventInfo.GetSpellInfo().Id)); - - caster.CastSpell(caster, SpellIds.DarkSimulacrumSpellpowerBuff, new CastSpellExtraArgs() - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(eventInfo.GetProcSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, GetTarget().SpellBaseDamageBonusDone(SpellSchoolMask.Magic)) - .AddSpellMod(SpellValueMod.BasePoint1, (int)GetTarget().SpellBaseHealingBonusDone(SpellSchoolMask.Magic))); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // Called by 206930 - Heart Strike +class spell_dk_heartbreaker : SpellScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.HeartbreakerTalent, SpellIds.HeartbreakerEnergize); } - [Script] // 77616 - Dark Simulacrum - class spell_dk_dark_simulacrum_buff : AuraScript + public override bool Load() { - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return aurEff.GetAmount() == eventInfo.GetSpellInfo().Id; - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.OverrideActionbarSpellsTriggered)); - } + return GetCaster().HasAura(SpellIds.HeartbreakerTalent); } - [Script] // 43265 - Death and Decay - class spell_dk_death_and_decay : AuraScript - { - void HandleDummyTick(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(GetTarget(), SpellIds.DeathAndDecayDamage, aurEff); - } - public override void Register() - { - OnEffectPeriodic.Add(new EffectPeriodicHandler(HandleDummyTick, 2, AuraType.PeriodicDummy)); - } + void HandleEnergize(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.HeartbreakerEnergize, new CastSpellExtraArgs() + .SetTriggeringSpell(GetSpell()) + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); } - [Script] // 47541 - Death Coil - class spell_dk_death_coil : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellIds.DeathCoilDamage, SpellIds.Unholy, SpellIds.UnholyVigor); - } + OnEffectHitTarget.Add(new(HandleEnergize, 0, SpellEffectName.Dummy)); + } +} - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - caster.CastSpell(GetHitUnit(), SpellIds.DeathCoilDamage, true); - AuraEffect unholyAura = caster.GetAuraEffect(SpellIds.Unholy, 6); - if (unholyAura != null) // can be any effect, just here to send SpellCastResult.DontReport on failure - caster.CastSpell(caster, SpellIds.UnholyVigor, unholyAura); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } +[Script] // 49184 - Howling Blast +class spell_dk_howling_blast : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FrostFever); } - [Script] // 52751 - Death Gate - class spell_dk_death_gate : SpellScript + void HandleFrostFever(uint effIndex) { - SpellCastResult CheckClass() - { - if (GetCaster().GetClass() != Class.Deathknight) - { - SetCustomCastResultMessage(SpellCustomErrors.MustBeDeathKnight); - return SpellCastResult.CustomError; - } + GetCaster().CastSpell(GetHitUnit(), SpellIds.FrostFever); + } - return SpellCastResult.SpellCastOk; - } + public override void Register() + { + OnEffectHitTarget.Add(new(HandleFrostFever, 0, SpellEffectName.SchoolDamage)); + } +} - void HandleScript(uint effIndex) +// Called by 45524 - Chains of Ice +[Script] // 454786 - Ice Prison +class spell_dk_ice_prison : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IcePrisonTalent, SpellIds.IcePrisonRoot); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.IcePrisonTalent); + } + + void HandleOnHit() + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.IcePrisonRoot, new CastSpellExtraArgs() { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] // 194878 - Icy Talons +class spell_dk_icy_talons : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell != null) + return procSpell.GetPowerTypeCostAmount(PowerType.RunicPower) > 0; + + return false; + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpellWithValue)); + } +} + +[Script] // 194879 - Icy Talons +class spell_dk_icy_talons_buff : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SmotheringOffense); + } + + void HandleSmotheringOffense(ref WorldObject target) + { + if (!GetCaster().HasAura(SpellIds.SmotheringOffense)) + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(HandleSmotheringOffense, 1, Targets.UnitCaster)); + } +} + +[Script] // 374277 - Improved Death Strike +class spell_dk_improved_death_strike : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Blood) + && ValidateSpellEffect((spellInfo.Id, 4)); + } + + void CalcHealIncrease(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + if (GetUnitOwner().HasAura(SpellIds.Blood)) + amount = GetEffectInfo(3).CalcValue(GetCaster()); + } + + void CalcPowerCostReduction(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + if (GetUnitOwner().HasAura(SpellIds.Blood)) + amount = GetEffectInfo(4).CalcValue(GetCaster()); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalcHealIncrease, 0, AuraType.AddPctModifier)); + DoEffectCalcAmount.Add(new(CalcHealIncrease, 1, AuraType.AddPctModifier)); + DoEffectCalcAmount.Add(new(CalcPowerCostReduction, 2, AuraType.AddFlatModifier)); + } +} + +[Script] // 206940 - Mark of Blood +class spell_dk_mark_of_blood : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MarkOfBloodHeal); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(eventInfo.GetProcTarget(), SpellIds.MarkOfBloodHeal, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 207346 - Necrosis +class spell_dk_necrosis : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NecrosisEffect); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.NecrosisEffect, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 207256 - Obliteration +class spell_dk_obliteration : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Obliteration, SpellIds.ObliterationRuneEnergize, SpellIds.KillingMachineProc) + && ValidateSpellEffect((SpellIds.Obliteration, 1)); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.KillingMachineProc, aurEff); + + AuraEffect oblitaration = target.GetAuraEffect(SpellIds.Obliteration, 1); + if (oblitaration != null) + if (RandomHelper.randChance(oblitaration.GetAmount())) + target.CastSpell(target, SpellIds.ObliterationRuneEnergize, aurEff); + } + + public override void Register() + { + AfterEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 207200 - Permafrost +class spell_dk_permafrost : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FrostShield); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), aurEff.GetAmount())); + GetTarget().CastSpell(GetTarget(), SpellIds.FrostShield, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +// 121916 - Glyph of the Geist (Unholy) +[Script] // 6.x, does this belong here or in spell_generic? apply this in creature_template_addon? sniffs say this is always cast on raise dead. +class spell_dk_pet_geist_transform : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlyphOfTheGeist); + } + + public override bool Load() + { + return GetCaster().IsPet(); + } + + SpellCastResult CheckCast() + { + Unit owner = GetCaster().GetOwner(); + if (owner != null) + if (owner.HasAura(SpellIds.GlyphOfTheGeist)) + return SpellCastResult.SpellCastOk; + + return SpellCastResult.SpellUnavailable; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + } +} + +// 147157 Glyph of the Skeleton (Unholy) +[Script] // 6.x, does this belong here or in spell_generic? apply this in creature_template_addon? sniffs say this is always cast on raise dead. +class spell_dk_pet_skeleton_transform : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlyphOfTheSkeleton); + } + + SpellCastResult CheckCast() + { + Unit owner = GetCaster().GetOwner(); + if (owner != null) + if (owner.HasAura(SpellIds.GlyphOfTheSkeleton)) + return SpellCastResult.SpellCastOk; + + return SpellCastResult.SpellUnavailable; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + } +} + +// 61257 - Runic Power Back on Snare/Root +[Script] // 7.1.5 +class spell_dk_pvp_4p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RunicReturn); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null) + return false; + + return (spellInfo.GetAllEffectsMechanicMask() & ((1 << (int)Mechanics.Root) | (1 << (int)Mechanics.Snare))) != 0; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + eventInfo.GetActionTarget().CastSpell(null, SpellIds.RunicReturn, true); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 46584 - Raise Dead +class spell_dk_raise_dead : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RaiseDeadSummon); + } + + void HandleDummy(uint effIndex) + { + uint spellId = SpellIds.RaiseDeadSummon; + GetCaster().CastSpell(null, spellId, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 440002 - Reaper of Souls (attached to 343294 - Soul Reaper) +class spell_dk_reaper_of_souls : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ReaperOfSoulsProc); + } + + bool IsAffectedByReaperOfSouls() + { + Aura reaperOfSouls = GetCaster().GetAura(SpellIds.ReaperOfSoulsProc); + if (reaperOfSouls != null) + return GetSpell().m_appliedMods.Contains(reaperOfSouls); + return false; + } + + void HandleDefault(ref WorldObject target) + { + if (IsAffectedByReaperOfSouls()) + target = null; + } + + void HandleReaperOfSouls(uint effIndex) + { + if (!IsAffectedByReaperOfSouls()) PreventHitDefaultEffect(effIndex); - Unit target = GetHitUnit(); - if (target != null) - target.CastSpell(target, (uint)GetEffectValue(), false); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckClass)); - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } } - [Script] // 49576 - Death Grip Initial - class spell_dk_death_grip_initial : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DeathGripDummy, SpellIds.DeathGripJump, SpellIds.DeathGripTaunt, SpellIds.Blood); - } + OnObjectTargetSelect.Add(new(HandleDefault, 1, Targets.UnitTargetEnemy)); + OnEffectLaunch.Add(new(HandleReaperOfSouls, 3, SpellEffectName.TriggerSpell)); + } +} - SpellCastResult CheckCast() - { - Unit caster = GetCaster(); - // Death Grip should not be castable while jumping/falling - if (caster.HasUnitState(UnitState.Jumping) || caster.HasUnitMovementFlag(MovementFlag.Falling)) - return SpellCastResult.Moving; - - return SpellCastResult.SpellCastOk; - } - - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.DeathGripDummy, true); - GetHitUnit().CastSpell(GetCaster(), SpellIds.DeathGripJump, true); - if (GetCaster().HasAura(SpellIds.Blood)) - GetCaster().CastSpell(GetHitUnit(), SpellIds.DeathGripTaunt, true); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); - } +[Script] // 59057 - Rime +class spell_dk_rime : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)) && ValidateSpellInfo(SpellIds.FrostScythe); } - [Script] // 48743 - Death Pact - class spell_dk_death_pact : AuraScript + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 2)); - } + float chance = (float)GetSpellInfo().GetEffect(1).CalcValue(GetTarget()); + if (eventInfo.GetSpellInfo().Id == SpellIds.FrostScythe) + chance /= 2.0f; - void HandleCalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit caster = GetCaster(); - if (caster != null) - amount = (int)caster.CountPctFromMaxHealth(GetEffectInfo(2).CalcValue(caster)); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(HandleCalcAmount, 1, AuraType.SchoolHealAbsorb)); - } + return RandomHelper.randChance(chance); } - [Script] // 49998 - Death Strike - class spell_dk_death_strike : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DeathStrikeEnabler, SpellIds.DeathStrikeHeal, SpellIds.BloodShieldMastery, SpellIds.BloodShieldAbsorb, SpellIds.Frost, SpellIds.DeathStrikeOffhand) - && ValidateSpellEffect((spellInfo.Id, 2)); - } + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); +// 343294 - Soul Reaper +// 469180 - Soul Reaper +[Script("spell_dk_soul_reaper", 1, 2)] +[Script("spell_dk_soul_reaper_reaper_of_souls", 0, null)] +class spell_dk_soul_reaper : AuraScript +{ + public spell_dk_soul_reaper(uint auraEffectIndex, uint? healthLimitEffectIndex) + { + _auraEffectIndex = (byte)auraEffectIndex; + _healthLimitEffectIndex = healthLimitEffectIndex; + } - AuraEffect enabler = caster.GetAuraEffect(SpellIds.DeathStrikeEnabler, 0, GetCaster().GetGUID()); - if (enabler != null) + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SoulReaper, SpellIds.SoulReaperDamage, SpellIds.RunicCorruption); + } + + void HandleOnTick(AuraEffect aurEff) + { + Unit target = GetTarget(); + Unit caster = GetCaster(); + if (caster == null) + return; + + if (!_healthLimitEffectIndex.HasValue || target.GetHealthPct() < (float)GetEffectInfo(_healthLimitEffectIndex.Value).CalcValue(caster)) + { + caster.CastSpell(target, SpellIds.SoulReaperDamage, new CastSpellExtraArgs() { - // Heals you for 25% of all damage taken in the last 5 sec, - int heal = MathFunctions.CalculatePct(enabler.CalculateAmount(GetCaster()), GetEffectInfo(1).CalcValue(GetCaster())); - // minimum 7.0% of maximum health. - int pctOfMaxHealth = MathFunctions.CalculatePct(GetEffectInfo(2).CalcValue(GetCaster()), caster.GetMaxHealth()); - heal = Math.Max(heal, pctOfMaxHealth); - - caster.CastSpell(caster, SpellIds.DeathStrikeHeal, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, heal)); - - AuraEffect aurEff = caster.GetAuraEffect(SpellIds.BloodShieldMastery, 0); - if (aurEff != null) - caster.CastSpell(caster, SpellIds.BloodShieldAbsorb, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, MathFunctions.CalculatePct(heal, aurEff.GetAmount()))); - - if (caster.HasAura(SpellIds.Frost)) - caster.CastSpell(GetHitUnit(), SpellIds.DeathStrikeOffhand, true); - } - } - - void TriggerRecentlyUsedDeathStrike() - { - GetCaster().CastSpell(GetCaster(), SpellIds.RecentlyUsedDeathStrike, true); - } - - public override void Register() - { - OnEffectLaunch.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); - AfterCast.Add(new(TriggerRecentlyUsedDeathStrike)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); } } - [Script] // 89832 - Death Strike Enabler - SpellDeathStrikeEnabler - class spell_dk_death_strike_enabler : AuraScript + void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) { - // Amount of seconds we calculate damage over - const byte LastSeconds = 5; + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) + return; - uint[] _damagePerSecond = new uint[LastSeconds]; + Player caster = GetCaster()?.ToPlayer(); + if (caster == null) + return; - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetDamageInfo() != null; - } - - void Update(AuraEffect aurEff) - { - // Move backwards all datas by one from [23][0][0][0][0] . [0][23][0][0][0] - _damagePerSecond = Enumerable.Range(1, _damagePerSecond.Length).Select(i => _damagePerSecond[i % _damagePerSecond.Length]).ToArray(); - _damagePerSecond[0] = 0; - } - - void HandleCalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - canBeRecalculated = true; - amount = Enumerable.Range(1, _damagePerSecond.Length).Sum(); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - _damagePerSecond[0] += eventInfo.GetDamageInfo().GetDamage(); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.PeriodicDummy)); - DoEffectCalcAmount.Add(new(HandleCalcAmount, 0, AuraType.PeriodicDummy)); - OnEffectUpdatePeriodic.Add(new(Update, 0, AuraType.PeriodicDummy)); - } - } - - [Script] // 85948 - Festering Strike - class spell_dk_festering_strike : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FesteringWound); - } - - void HandleScriptEffect(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.FesteringWound, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, GetEffectValue())); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.Dummy)); - } - } - - [Script] // 47496 - Explode, Ghoul spell for Corpse Explosion - class spell_dk_ghoul_explode : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CorpseExplosionTriggered) && ValidateSpellEffect((spellInfo.Id, 2)); - } - - void HandleDamage(uint effIndex) - { - SetHitDamage((int)GetCaster().CountPctFromMaxHealth(GetEffectInfo(2).CalcValue(GetCaster()))); - } - - void Suicide(uint effIndex) - { - Unit unitTarget = GetHitUnit(); - if (unitTarget != null) + if (caster.IsHonorOrXPTarget(GetTarget())) + caster.CastSpell(caster, SpellIds.RunicCorruption, new CastSpellExtraArgs() { - // Corpse Explosion (Suicide) - unitTarget.CastSpell(unitTarget, SpellIds.CorpseExplosionTriggered, true); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleOnTick, _auraEffectIndex, AuraType.PeriodicDummy)); + AfterEffectRemove.Add(new(RemoveEffect, _auraEffectIndex, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); + } + + + byte _auraEffectIndex; + uint? _healthLimitEffectIndex; +} + +// Called by 383312 Abomination Limb and 49576 - Death Grip +[Script] // 454822 - Subduing Grasp +class spell_dk_subduing_grasp : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SubduingGraspTalent, SpellIds.SubduingGraspDebuff); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.SubduingGraspTalent); + } + + void HandleSubduingGrasp(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.SubduingGraspDebuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + if (m_scriptSpellId == SpellIds.GorefiendsGrasp) + OnEffectHitTarget.Add(new(HandleSubduingGrasp, 1, SpellEffectName.ScriptEffect)); + else + OnEffectHitTarget.Add(new(HandleSubduingGrasp, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 242057 - Rune Empowered +class spell_dk_t20_2p_rune_empowered : AuraScript +{ + int _runicPowerSpent = 0; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PillarOfFrost, SpellIds.BreathOfSindragosa); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Spell procSpell = procInfo.GetProcSpell(); + if (procSpell == null) + return; + + Aura pillarOfFrost = GetTarget().GetAura(SpellIds.PillarOfFrost); + if (pillarOfFrost == null) + return; + + _runicPowerSpent += procSpell.GetPowerTypeCostAmount(PowerType.RunicPower).GetValueOrDefault(0); + // Breath of Sindragosa special case + SpellInfo breathOfSindragosa = Global.SpellMgr.GetSpellInfo(SpellIds.BreathOfSindragosa, Difficulty.None); + if (procSpell.IsTriggeredByAura(breathOfSindragosa)) + { + var powerRecord = breathOfSindragosa.PowerCosts.ToList().Find(power => power.PowerType == PowerType.RunicPower && power.PowerPctPerSecond > 0.0f); + if (powerRecord != null) + _runicPowerSpent += MathFunctions.CalculatePct(GetTarget().GetMaxPower(PowerType.RunicPower), powerRecord.PowerPctPerSecond); } - public override void Register() + if (_runicPowerSpent >= 600) { - OnEffectHitTarget.Add(new(HandleDamage, 0, SpellEffectName.SchoolDamage)); - OnEffectHitTarget.Add(new(Suicide, 1, SpellEffectName.SchoolDamage)); + pillarOfFrost.SetDuration(pillarOfFrost.GetDuration() + 1000); + _runicPowerSpent -= 600; } } - [Script] // 69961 - Glyph of Scourge Strike - class spell_dk_glyph_of_scourge_strike_script : SpellScript + public override void Register() { - void HandleScriptEffect(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - var mPeriodic = target.GetAuraEffectsByType(AuraType.PeriodicDamage); - foreach (var aurEff in mPeriodic) - { - SpellInfo spellInfo = aurEff.GetSpellInfo(); - // search our Blood Plague and Frost Fever on target - if (spellInfo.SpellFamilyName == SpellFamilyNames.Deathknight && (spellInfo.SpellFamilyFlags[2] & 0x2) != 0 && - aurEff.GetCasterGUID() == caster.GetGUID()) - { - int countMin = aurEff.GetBase().GetMaxDuration(); - int countMax = spellInfo.GetMaxDuration(); - - // this Glyph - countMax += 9000; - - if (countMin < countMax) - { - aurEff.GetBase().SetDuration(aurEff.GetBase().GetDuration() + 3000); - aurEff.GetBase().SetMaxDuration(countMin + 3000); - } - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } +[Script] // 55233 - Vampiric Blood +class spell_dk_vampiric_blood : AuraScript +{ + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + amount = (int)GetUnitOwner().CountPctFromMaxHealth(amount); } - [Script] // 49184 - Howling Blast - class spell_dk_howling_blast : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FrostFever); - } + DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ModIncreaseHealth2)); + } +} - void HandleFrostFever(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.FrostFever); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleFrostFever, 0, SpellEffectName.SchoolDamage)); - } +[Script] // 273953 - Voracious (attached to 49998 - Death Strike) +class spell_dk_voracious : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DhVoraciousTalent, SpellIds.DhVoraciousLeech); } - [Script] // 206940 - Mark of Blood - class spell_dk_mark_of_blood : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MarkOfBloodHeal); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(eventInfo.GetProcTarget(), SpellIds.MarkOfBloodHeal, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + return GetCaster().HasAura(SpellIds.DhVoraciousTalent); } - [Script] // 207346 - Necrosis - class spell_dk_necrosis : AuraScript + void HandleHit(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) + Unit caster = GetCaster(); + caster.CastSpell(caster, SpellIds.DhVoraciousLeech, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.NecrosisEffect); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.NecrosisEffect, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } - [Script] // 207256 - Obliteration - class spell_dk_obliteration : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Obliteration, SpellIds.ObliterationRuneEnergize, SpellIds.KillingMachineProc) - && ValidateSpellEffect((SpellIds.Obliteration, 1)); - } + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit target = GetTarget(); - target.CastSpell(target, SpellIds.KillingMachineProc, aurEff); +[Script] // 43265 - Death and Decay +class at_dk_death_and_decay(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnUnitEnter(Unit unit) + { + if (unit.GetGUID() != at.GetCasterGUID()) + return; - AuraEffect oblitaration = target.GetAuraEffect(SpellIds.Obliteration, 1); - if (oblitaration != null) - if (RandomHelper.randChance(oblitaration.GetAmount())) - target.CastSpell(target, SpellIds.ObliterationRuneEnergize, aurEff); - } + if (unit.HasAura(SpellIds.CleavingStrikes)) + unit.CastSpell(unit, SpellIds.DeathAndDecayIncreaseTargets, TriggerCastFlags.DontReportCastError); - public override void Register() - { - AfterEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + if (unit.HasAura(SpellIds.SanguineGroundTalent)) + unit.CastSpell(unit, SpellIds.SanguineGround); } - [Script] // 207200 - Permafrost - class spell_dk_permafrost : AuraScript + public override void OnUnitExit(Unit unit) { - public override bool Validate(SpellInfo spellInfo) + if (unit.GetGUID() != at.GetCasterGUID()) + return; + + Aura deathAndDecay = unit.GetAura(SpellIds.DeathAndDecayIncreaseTargets); + if (deathAndDecay != null) { - return ValidateSpellInfo(SpellIds.FrostShield); + AuraEffect cleavingStrikes = unit.GetAuraEffect(SpellIds.CleavingStrikes, 3); + if (cleavingStrikes != null) + + deathAndDecay.SetDuration(cleavingStrikes.GetAmount()); } - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), aurEff.GetAmount())); - GetTarget().CastSpell(GetTarget(), SpellIds.FrostShield, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - // 121916 - Glyph of the Geist (Unholy) - [Script] /// 6.x, does this belong here or in spell_generic? apply this in creature_template_addon? sniffs say this is always cast on raise dead. - class spell_dk_pet_geist_transform : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlyphOfTheGeist); - } - - public override bool Load() - { - return GetCaster().IsPet(); - } - - SpellCastResult CheckCast() - { - Unit owner = GetCaster().GetOwner(); - if (owner != null) - if (owner.HasAura(SpellIds.GlyphOfTheGeist)) - return SpellCastResult.SpellCastOk; - - return SpellCastResult.SpellUnavailable; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - } - } - - // 147157 Glyph of the Skeleton (Unholy) - [Script] /// 6.x, does this belong here or in spell_generic? apply this in creature_template_addon? sniffs say this is always cast on raise dead. - class spell_dk_pet_skeleton_transform : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlyphOfTheSkeleton); - } - - SpellCastResult CheckCast() - { - Unit owner = GetCaster().GetOwner(); - if (owner != null) - if (owner.HasAura(SpellIds.GlyphOfTheSkeleton)) - return SpellCastResult.SpellCastOk; - - return SpellCastResult.SpellUnavailable; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - } - } - - // 61257 - Runic Power Back on Snare/Root - [Script] /// 7.1.5 - class spell_dk_pvp_4p_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RunicReturn); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null) - return false; - - return (spellInfo.GetAllEffectsMechanicMask() & ((1 << (int)Mechanics.Root) | (1 << (int)Mechanics.Snare))) != 0; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - eventInfo.GetActionTarget().CastSpell(null, SpellIds.RunicReturn, true); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 46584 - Raise Dead - class spell_dk_raise_dead : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RaiseDeadSummon, SpellIds.SludgeBelcher, SpellIds.SludgeBelcherSummon); - } - - void HandleDummy(uint effIndex) - { - uint spellId = SpellIds.RaiseDeadSummon; - if (GetCaster().HasAura(SpellIds.SludgeBelcher)) - spellId = SpellIds.SludgeBelcherSummon; - - GetCaster().CastSpell(null, spellId, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 59057 - Rime - class spell_dk_rime : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)) && ValidateSpellInfo(SpellIds.FrostScythe); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - float chance = (float)GetSpellInfo().GetEffect(1).CalcValue(GetTarget()); - if (eventInfo.GetSpellInfo().Id == SpellIds.FrostScythe) - chance /= 2.0f; - - return RandomHelper.randChance(chance); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 242057 - Rune Empowered - class spell_dk_t20_2p_rune_empowered : AuraScript - { - int _runicPowerSpent; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PillarOfFrost, SpellIds.BreathOfSindragosa); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Spell procSpell = procInfo.GetProcSpell(); - if (procSpell == null) - return; - - Aura pillarOfFrost = GetTarget().GetAura(SpellIds.PillarOfFrost); - if (pillarOfFrost == null) - return; - - _runicPowerSpent += procSpell.GetPowerTypeCostAmount(PowerType.RunicPower).GetValueOrDefault(0); - // Breath of Math.Sindragosa special case - SpellInfo breathOfSindragosa = SpellMgr.GetSpellInfo(SpellIds.BreathOfSindragosa, Difficulty.None); - if (procSpell.IsTriggeredByAura(breathOfSindragosa)) - { - var powerRecord = breathOfSindragosa.PowerCosts.ToList().Find(power => power.PowerType == PowerType.RunicPower && power.PowerPctPerSecond > 0.0f); - if (powerRecord != null) - _runicPowerSpent += MathFunctions.CalculatePct(GetTarget().GetMaxPower(PowerType.RunicPower), powerRecord.PowerPctPerSecond); - } - - if (_runicPowerSpent >= 600) - { - pillarOfFrost.SetDuration(pillarOfFrost.GetDuration() + 1000); - _runicPowerSpent -= 600; - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 55233 - Vampiric Blood - class spell_dk_vampiric_blood : AuraScript - { - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - amount = (int)GetUnitOwner().CountPctFromMaxHealth(amount); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ModIncreaseHealth2)); - } - } - - [Script] // 43265 - Death and Decay - class at_dk_death_and_decay : AreaTriggerAI - { - public at_dk_death_and_decay(AreaTrigger areatrigger) : base(areatrigger) { } - - public override void OnUnitEnter(Unit unit) - { - Unit caster = at.GetCaster(); - if (caster != null) - { - if (caster == unit) - { - if (caster.HasAura(SpellIds.UnholyGroundTalent)) - caster.CastSpell(caster, SpellIds.UnholyGroundHaste); - } - } - } - - public override void OnUnitExit(Unit unit) - { - unit.RemoveAurasDueToSpell(SpellIds.UnholyGroundHaste); - } + unit.RemoveAurasDueToSpell(SpellIds.SanguineGround); } } \ No newline at end of file diff --git a/Source/Scripts/Spells/DemonHunter.cs b/Source/Scripts/Spells/DemonHunter.cs index a75e2130e..fc96ccdf9 100644 --- a/Source/Scripts/Spells/DemonHunter.cs +++ b/Source/Scripts/Spells/DemonHunter.cs @@ -1,447 +1,1747 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Framework.Dynamic; using Game.AI; +using Game.DataStorage; using Game.Entities; +using Game.Movement; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; using System.Linq; -using static Global; +namespace Scripts.Spells.DemonHunter; -namespace Scripts.Spells.DemonHunter +struct SpellIds { - struct SpellIds + public const uint AreatriggerDhShatteredSoulsHavoc = 8352; + public const uint AreatriggerDhShatteredSoulsHavocDemon = 11231; + public const uint AreatriggerDhShatteredSoulsVengeance = 11266; + public const uint AreatriggerDhShatteredSoulsVengeanceDemon = 10693; + public const uint AreatriggerDhSoulFragmentHavoc = 12929; + public const uint AreatriggerDhSoulFragmentVengeance = 10665; + + public const uint AbyssalStrike = 207550; + public const uint Annihilation = 201427; + public const uint AnnihilationMh = 227518; + public const uint AnnihilationOh = 201428; + public const uint ArmyUntoOneself = 442714; + public const uint AwakenTheDemonWithinCd = 207128; + public const uint BladeWard = 442715; + public const uint Blur = 212800; + public const uint BlurTrigger = 198589; + public const uint BurningAlive = 207739; + public const uint BurningAliveTargetSelector = 207760; + public const uint CalcifiedSpikesTalent = 389720; + public const uint CalcifiedSpikesModDamage = 391171; + public const uint ChaosNova = 179057; + public const uint ChaosStrike = 162794; + public const uint ChaosStrikeEnergize = 193840; + public const uint ChaosStrikeMh = 222031; + public const uint ChaosStrikeOh = 199547; + public const uint ChaosTheoryTalent = 389687; + public const uint ChaosTheoryCrit = 390195; + public const uint ChaoticTransformation = 388112; + public const uint CharredWarbladesHeal = 213011; + public const uint CollectiveAnguish = 390152; + public const uint CollectiveAnguishEyeBeam = 391057; + public const uint CollectiveAnguishEyeBeamDamage = 391058; + public const uint CollectiveAnguishFelDevastation = 393831; + public const uint ConsumeSoulHavoc = 228542; + public const uint ConsumeSoulHavocDemon = 228556; + public const uint ConsumeSoulHavocShattered = 228540; + public const uint ConsumeSoulHeal = 203794; + public const uint ConsumeSoulVengeance = 208014; + public const uint ConsumeSoulVengeanceDemon = 210050; + public const uint ConsumeSoulVengeanceShattered = 210047; + public const uint CycleOfHatredTalent = 258887; + public const uint CycleOfHatredCooldownReduction = 1214887; + public const uint CycleOfHatredRemoveStacks = 1214890; + public const uint DarkglareBoon = 389708; + public const uint DarkglareBoonEnergize = 391345; + public const uint DarknessAbsorb = 209426; + public const uint DeflectingSpikes = 321028; + public const uint DemonBladesDmg = 203796; + public const uint DemonSpikes = 203819; + public const uint DemonSpikesTrigger = 203720; + public const uint Demonic = 213410; + public const uint DemonicOrigins = 235893; + public const uint DemonicOriginsBuff = 235894; + public const uint DemonicTrampleDmg = 208645; + public const uint DemonicTrampleStun = 213491; + public const uint DemonsBite = 162243; + public const uint EssenceBreakDebuff = 320338; + public const uint EyeBeam = 198013; + public const uint EyeBeamDamage = 198030; + public const uint EyeOfLeotherasDmg = 206650; + public const uint FeastOfSouls = 207697; + public const uint FeastOfSoulsPeriodicHeal = 207693; + public const uint FeedTheDemon = 218612; + public const uint FelBarrage = 211053; + public const uint FelBarrageDmg = 211052; + public const uint FelBarrageProc = 222703; + public const uint FelDevastation = 212084; + public const uint FelDevastationDmg = 212105; + public const uint FelDevastationHeal = 212106; + public const uint FelFlameFortificationTalent = 389705; + public const uint FelFlameFortificationModDamage = 393009; + public const uint FelRush = 195072; + public const uint FelRushDmg = 192611; + public const uint FelRushGround = 197922; + public const uint FelRushWaterAir = 197923; + public const uint Felblade = 232893; + public const uint FelbladeCharge = 213241; + public const uint FelbladeCooldownResetProcHavoc = 236167; + public const uint FelbladeCooldownResetProcVengeance = 203557; + public const uint FelbladeCooldownResetProcVisual = 204497; + public const uint FelbladeDamage = 213243; + public const uint FieryBrand = 204021; + public const uint FieryBrandRank2 = 320962; + public const uint FieryBrandDebuffRank1 = 207744; + public const uint FieryBrandDebuffRank2 = 207771; + public const uint FirstBlood = 206416; + public const uint FlameCrash = 227322; + public const uint Frailty = 224509; + public const uint FuriousGaze = 343311; + public const uint FuriousGazeBuff = 343312; + public const uint FuriousThrows = 393029; + public const uint GlaiveTempest = 342857; + public const uint Glide = 131347; + public const uint GlideDuration = 197154; + public const uint GlideKnockback = 196353; + public const uint HavocMastery = 185164; + public const uint IllidansGrasp = 205630; + public const uint IllidansGraspDamage = 208618; + public const uint IllidansGraspJumpDest = 208175; + public const uint ImmolationAura = 258920; + public const uint InnerDemonBuff = 390145; + public const uint InnerDemonDamage = 390137; + public const uint InnerDemonTalent = 389693; + public const uint InfernalStrikeCast = 189110; + public const uint InfernalStrikeImpactDamage = 189112; + public const uint InfernalStrikeJump = 189111; + public const uint JaggedSpikes = 205627; + public const uint JaggedSpikesDmg = 208790; + public const uint JaggedSpikesProc = 208796; + public const uint ManaRiftDmgPowerBurn = 235904; + public const uint Metamorphosis = 191428; + public const uint MetamorphosisDummy = 191427; + public const uint MetamorphosisImpactDamage = 200166; + public const uint MetamorphosisReset = 320645; + public const uint MetamorphosisTransform = 162264; + public const uint MetamorphosisVengeanceTransform = 187827; + public const uint Momentum = 208628; + public const uint MonsterRisingAgility = 452550; + public const uint NemesisAberrations = 208607; + public const uint NemesisBeasts = 208608; + public const uint NemesisCritters = 208609; + public const uint NemesisDemons = 208608; + public const uint NemesisDragonkin = 208610; + public const uint NemesisElementals = 208611; + public const uint NemesisGiants = 208612; + public const uint NemesisHumanoids = 208605; + public const uint NemesisMechanicals = 208613; + public const uint NemesisUndead = 208614; + public const uint RainFromAbove = 206803; + public const uint RainOfChaos = 205628; + public const uint RainOfChaosImpact = 232538; + public const uint RazorSpikes = 210003; + public const uint RestlessHunterTalent = 390142; + public const uint RestlessHunterBuff = 390212; + public const uint Sever = 235964; + public const uint ShatterSoul = 209980; + public const uint ShatterSoul1 = 209981; + public const uint ShatterSoul2 = 210038; + public const uint ShatteredSoul = 226258; + public const uint ShatteredSoulLesserSoulFragment1 = 228533; + public const uint ShatteredSoulLesserSoulFragment2 = 237867; + public const uint Shear = 203782; + public const uint SigilOfChainsAreaSelector = 204834; + public const uint SigilOfChainsGrip = 208674; + public const uint SigilOfChainsJump = 208674; + public const uint SigilOfChainsSlow = 204843; + public const uint SigilOfChainsSnare = 204843; + public const uint SigilOfChainsTargetSelect = 204834; + public const uint SigilOfChainsVisual = 208673; + public const uint SigilOfFlame = 204596; + public const uint SigilOfFlameAoe = 204598; + public const uint SigilOfFlameFlameCrash = 228973; + public const uint SigilOfFlameVisual = 208710; + public const uint SigilOfMisery = 207685; + public const uint SigilOfMiseryAoe = 207685; + public const uint SigilOfSilence = 204490; + public const uint SigilOfSilenceAoe = 204490; + public const uint SoulBarrier = 227225; + public const uint SoulCleave = 228477; + public const uint SoulCleaveDmg = 228478; + public const uint SoulFragmentCounter = 203981; + public const uint SoulFurnaceDamageBuff = 391172; + public const uint SoulRending = 204909; + public const uint SpiritBombDamage = 218677; + public const uint SpiritBombHeal = 227255; + public const uint SpiritBombVisual = 218678; + public const uint StudentOfSufferingTalent = 452412; + public const uint StudentOfSufferingAura = 453239; + public const uint TacticalRetreatEnergize = 389890; + public const uint TacticalRetreatTalent = 389688; + public const uint ThrowGlaive = 185123; + public const uint UncontainedFel = 209261; + public const uint VengeanceDemonHunter = 212613; + public const uint VengefulBonds = 320635; + public const uint VengefulRetreat = 198813; + public const uint VengefulRetreatTrigger = 198793; + + public const uint CategoryEyeBeam = 1582; + public const uint CategoryBladeDance = 1640; +} + +[Script] // Called by 232893 - Felblade +class spell_dh_army_unto_oneself : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - public const uint AbyssalStrike = 207550; - public const uint Annihilation = 201427; - public const uint AnnihilationMh = 227518; - public const uint AnnihilationOh = 201428; - public const uint AwakenTheDemonWithinCd = 207128; - public const uint Blur = 212800; - public const uint BlurTrigger = 198589; - public const uint BurningAlive = 207739; - public const uint BurningAliveTargetSelector = 207760; - public const uint ChaosNova = 179057; - public const uint ChaosStrike = 162794; - public const uint ChaosStrikeEnergize = 193840; - public const uint ChaosStrikeMh = 222031; - public const uint ChaosStrikeOh = 199547; - public const uint ConsumeSoulHavoc = 228542; - public const uint ConsumeSoulHavocDemon = 228556; - public const uint ConsumeSoulHavocShattered = 228540; - public const uint ConsumeSoulHeal = 203794; - public const uint ConsumeSoulVengeance = 208014; - public const uint ConsumeSoulVengeanceDemon = 210050; - public const uint ConsumeSoulVengeanceShattered = 210047; - public const uint DarknessAbsorb = 209426; - public const uint DemonBladesDmg = 203796; - public const uint DemonSpikes = 203819; - public const uint DemonSpikesTrigger = 203720; - public const uint Demonic = 213410; - public const uint DemonicOrigins = 235893; - public const uint DemonicOriginsBuff = 235894; - public const uint DemonicTrampleDmg = 208645; - public const uint DemonicTrampleStun = 213491; - public const uint DemonsBite = 162243; - public const uint EyeBeam = 198013; - public const uint EyeBeamDmg = 198030; - public const uint EyeOfLeotherasDmg = 206650; - public const uint FeastOfSouls = 207697; - public const uint FeastOfSoulsPeriodicHeal = 207693; - public const uint FeedTheDemon = 218612; - public const uint FelBarrage = 211053; - public const uint FelBarrageDmg = 211052; - public const uint FelBarrageProc = 222703; - public const uint FelDevastation = 212084; - public const uint FelDevastationDmg = 212105; - public const uint FelDevastationHeal = 212106; - public const uint FelRush = 195072; - public const uint FelRushDmg = 192611; - public const uint FelRushGround = 197922; - public const uint FelRushWaterAir = 197923; - public const uint Felblade = 232893; - public const uint FelbladeCharge = 213241; - public const uint FelbladeDmg = 213243; - public const uint FelbladeProc = 203557; - public const uint FelbladeProcVisual = 204497; - public const uint FelbladeProc1 = 236167; - public const uint FieryBrand = 204021; - public const uint FieryBrandDmgReductionDebuff = 207744; - public const uint FieryBrandDot = 207771; - public const uint FirstBlood = 206416; - public const uint FlameCrash = 227322; - public const uint Frailty = 224509; - public const uint Glide = 131347; - public const uint GlideDuration = 197154; - public const uint GlideKnockback = 196353; - public const uint HavocMastery = 185164; - public const uint IllidansGrasp = 205630; - public const uint IllidansGraspDamage = 208618; - public const uint IllidansGraspJumpDest = 208175; - public const uint InfernalStrikeCast = 189110; - public const uint InfernalStrikeImpactDamage = 189112; - public const uint InfernalStrikeJump = 189111; - public const uint JaggedSpikes = 205627; - public const uint JaggedSpikesDmg = 208790; - public const uint JaggedSpikesProc = 208796; - public const uint ManaRiftDmgPowerBurn = 235904; - public const uint Metamorphosis = 191428; - public const uint MetamorphosisDummy = 191427; - public const uint MetamorphosisImpactDamage = 200166; - public const uint MetamorphosisReset = 320645; - public const uint MetamorphosisTransform = 162264; - public const uint MetamorphosisVengeanceTransform = 187827; - public const uint Momentum = 208628; - public const uint NemesisAberrations = 208607; - public const uint NemesisBeasts = 208608; - public const uint NemesisCritters = 208609; - public const uint NemesisDemons = 208608; - public const uint NemesisDragonkin = 208610; - public const uint NemesisElementals = 208611; - public const uint NemesisGiants = 208612; - public const uint NemesisHumanoids = 208605; - public const uint NemesisMechanicals = 208613; - public const uint NemesisUndead = 208614; - public const uint RainFromAbove = 206803; - public const uint RainOfChaos = 205628; - public const uint RainOfChaosImpact = 232538; - public const uint RazorSpikes = 210003; - public const uint Sever = 235964; - public const uint ShatterSoul = 209980; - public const uint ShatterSoul1 = 209981; - public const uint ShatterSoul2 = 210038; - public const uint ShatteredSoul = 226258; - public const uint ShatteredSoulLesserSoulFragment1 = 228533; - public const uint ShatteredSoulLesserSoulFragment2 = 237867; - public const uint Shear = 203782; - public const uint SigilOfChainsAreaSelector = 204834; - public const uint SigilOfChainsGrip = 208674; - public const uint SigilOfChainsJump = 208674; - public const uint SigilOfChainsSlow = 204843; - public const uint SigilOfChainsSnare = 204843; - public const uint SigilOfChainsTargetSelect = 204834; - public const uint SigilOfChainsVisual = 208673; - public const uint SigilOfFlameAoe = 204598; - public const uint SigilOfFlameDamage = 204598; - public const uint SigilOfFlameFlameCrash = 228973; - public const uint SigilOfMisery = 207685; - public const uint SigilOfMiseryAoe = 207685; - public const uint SigilOfSilence = 204490; - public const uint SigilOfSilenceAoe = 204490; - public const uint SoulBarrier = 227225; - public const uint SoulCleave = 228477; - public const uint SoulCleaveDmg = 228478; - public const uint SoulFragmentCounter = 203981; - public const uint SoulFurnaceDamageBuff = 391172; - public const uint SoulRending = 204909; - public const uint SpiritBombDamage = 218677; - public const uint SpiritBombHeal = 227255; - public const uint SpiritBombVisual = 218678; - public const uint ThrowGlaive = 185123; - public const uint UncontainedFel = 209261; - public const uint VengefulRetreat = 198813; - public const uint VengefulRetreatTrigger = 198793; + return ValidateSpellInfo(SpellIds.ArmyUntoOneself, SpellIds.BladeWard); } - [Script] // 197125 - Chaos Strike - class spell_dh_chaos_strike : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ChaosStrikeEnergize); - } + return GetCaster().HasAura(SpellIds.ArmyUntoOneself); + } - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + void ApplyBladeWard() + { + GetCaster().CastSpell(GetCaster(), SpellIds.BladeWard, new CastSpellExtraArgs() { - PreventDefaultAction(); - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount()); - args.SetTriggeringAura(aurEff); - GetTarget().CastSpell(GetTarget(), SpellIds.ChaosStrikeEnergize, args); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } - public override void Register() + public override void Register() + { + AfterCast.Add(new(ApplyBladeWard)); + } +} + +[Script] // Called by 203819 - Demon Spikes +class spell_dh_calcified_spikes : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CalcifiedSpikesTalent, SpellIds.CalcifiedSpikesModDamage); + } + + public override bool Load() + { + return GetUnitOwner().HasAura(SpellIds.CalcifiedSpikesTalent); + } + + void HandleAfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.CalcifiedSpikesModDamage, new CastSpellExtraArgs() { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleAfterRemove, 1, AuraType.ModArmorPctFromStat, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +[Script] // 391171 - Calcified Spikes +class spell_dh_calcified_spikes_periodic : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void HandlePeriodic(AuraEffect aurEff) + { + AuraEffect damagePctTaken = GetEffect(0); + if (damagePctTaken != null) + damagePctTaken.ChangeAmount(damagePctTaken.GetAmount() + 1); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodic, 1, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 197125 - Chaos Strike +class spell_dh_chaos_strike : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChaosStrikeEnergize); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.ChaosStrikeEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = eventInfo.GetProcSpell() + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 344862 - Chaos Strike +class spell_dh_chaos_strike_initial : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChaosStrike); + } + + void HandleHit(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ChaosStrike, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.Dummy)); + } +} + +[Script] // Called by 188499 - Blade Dance and 210152 - Death Sweep +class spell_dh_chaos_theory : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (!ValidateSpellInfo(SpellIds.ChaosTheoryCrit) + || !ValidateSpellEffect((SpellIds.ChaosTheoryTalent, 1))) + return false; + + SpellInfo chaosTheory = Global.SpellMgr.GetSpellInfo(SpellIds.ChaosTheoryTalent, Difficulty.None); + return chaosTheory.GetEffect(0).CalcValue() < chaosTheory.GetEffect(1).CalcValue(); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ChaosTheoryTalent); + } + + void ChaosTheory() + { + Unit caster = GetCaster(); + Aura chaosTheory = caster.GetAura(SpellIds.ChaosTheoryTalent); + if (chaosTheory == null) + return; + + AuraEffect min = chaosTheory.GetEffect(0); + AuraEffect max = chaosTheory.GetEffect(1); + if (min == null || max == null) + return; + + int critChance = RandomHelper.IRand(min.GetAmount(), max.GetAmount()); + caster.CastSpell(caster, SpellIds.ChaosTheoryCrit, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, critChance) } + }); + } + + public override void Register() + { + AfterCast.Add(new(ChaosTheory)); + } +} + +[Script] // 390195 - Chaos Theory +class spell_dh_chaos_theory_drop_charge : AuraScript +{ + void Prepare(ProcEventInfo eventInfo) + { + PreventDefaultAction(); + // delayed charge drop - this aura must be removed after Chaos Strike does damage and after it procs power refund + GetAura().DropChargeDelayed(500); + } + + public override void Register() + { + DoPrepareProc.Add(new(Prepare)); + } +} + +[Script] // Called by 191427 - Metamorphosis +class spell_dh_chaotic_transformation : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChaoticTransformation) + && CliDB.SpellCategoryStorage.ContainsKey(SpellIds.CategoryEyeBeam) + && CliDB.SpellCategoryStorage.ContainsKey(SpellIds.CategoryBladeDance); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ChaoticTransformation); + } + + void HandleCooldown() + { + GetCaster().GetSpellHistory().ResetCooldowns(cooldown => + { + uint category = Global.SpellMgr.GetSpellInfo(cooldown.SpellId, Difficulty.None).CategoryId; + return category == SpellIds.CategoryEyeBeam || category == SpellIds.CategoryBladeDance; + }, true); + } + + public override void Register() + { + AfterCast.Add(new(HandleCooldown)); + } +} + +[Script] // 213010 - Charred Warblades +class spell_dh_charred_warblades : AuraScript +{ + uint _healAmount = 0; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CharredWarbladesHeal); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo() != null && (eventInfo.GetDamageInfo().GetSchoolMask() & SpellSchoolMask.Fire) != 0; + } + + void HandleAfterProc(ProcEventInfo eventInfo) + { + _healAmount += MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), GetEffect(0).GetAmount()); + } + + void HandleDummyTick(AuraEffect aurEff) + { + if (_healAmount == 0) + return; + + GetTarget().CastSpell(GetTarget(), SpellIds.CharredWarbladesHeal, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringAura(aurEff) + .AddSpellMod(SpellValueMod.BasePoint0, (int)_healAmount)); + + _healAmount = 0; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + AfterProc.Add(new(HandleAfterProc)); + OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // Called by 212084 - Fel Devastation and 198013 - Eye Beam +class spell_dh_collective_anguish : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CollectiveAnguish, SpellIds.FelDevastation, SpellIds.CollectiveAnguishEyeBeam, SpellIds.CollectiveAnguishFelDevastation); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.CollectiveAnguish); + } + + void HandleEyeBeam() + { + GetCaster().CastSpell(GetCaster(), SpellIds.CollectiveAnguishEyeBeam, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + void HandleFelDevastation() + { + GetCaster().CastSpell(GetCaster(), SpellIds.CollectiveAnguishFelDevastation, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + if (m_scriptSpellId == SpellIds.FelDevastation) + AfterCast.Add(new(HandleEyeBeam)); + else + AfterCast.Add(new(HandleFelDevastation)); + } +} + +[Script] // 391057 - Eye Beam +class spell_dh_collective_anguish_eye_beam : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CollectiveAnguishEyeBeamDamage); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + { + caster.CastSpell(null, SpellIds.CollectiveAnguishEyeBeamDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); } } - [Script] // 206416 - First Blood - class spell_dh_first_blood : AuraScript + public override void Register() { - ObjectGuid _firstTargetGUID; + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); + } +} - public ObjectGuid GetFirstTarget() { return _firstTargetGUID; } - - public void SetFirstTarget(ObjectGuid targetGuid) { _firstTargetGUID = targetGuid; } - - public override void Register() { } +[Script] // 320413 - Critical Chaos +class spell_dh_critical_chaos : AuraScript +{ + void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + AuraEffect amountHolder = GetEffect(1); + if (amountHolder != null) + { + float critChanceDone = GetUnitOwner().GetUnitCriticalChanceDone(WeaponAttackType.BaseAttack); + amount = (int)MathFunctions.CalculatePct(critChanceDone, amountHolder.GetAmount()); + } } - // 188499 - Blade Dance - [Script] // 210152 - Death Sweep - class spell_dh_blade_dance : SpellScript + void UpdatePeriodic(AuraEffect aurEff) { - public override bool Validate(SpellInfo spellInfo) + AuraEffect bonus = GetEffect(0); + if (bonus != null) + bonus.RecalculateAmount(aurEff); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalcAmount, 0, AuraType.AddFlatModifier)); + OnEffectPeriodic.Add(new(UpdatePeriodic, 1, AuraType.PeriodicDummy)); + } +} + +[Script] // Called by 198013 - Eye Beam +class spell_dh_cycle_of_hatred : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CycleOfHatredTalent, SpellIds.CycleOfHatredCooldownReduction, SpellIds.CycleOfHatredRemoveStacks); + } + + public override bool Load() + { + return GetCaster().HasAuraEffect(SpellIds.CycleOfHatredTalent, 0); + } + + void HandleCycleOfHatred() + { + Unit caster = GetCaster(); + + // First calculate cooldown then add another stack + uint cycleOfHatredStack = caster.GetAuraCount(SpellIds.CycleOfHatredCooldownReduction); + AuraEffect cycleOfHatred = caster.GetAuraEffect(SpellIds.CycleOfHatredTalent, 0); + caster.GetSpellHistory().ModifyCooldown(GetSpellInfo(), -TimeSpan.FromSeconds(cycleOfHatred.GetAmount() * cycleOfHatredStack)); + + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + args.SetTriggeringSpell(GetSpell()); + + caster.CastSpell(caster, SpellIds.CycleOfHatredCooldownReduction, args); + caster.CastSpell(caster, SpellIds.CycleOfHatredRemoveStacks, args); + } + + public override void Register() + { + AfterCast.Add(new(HandleCycleOfHatred)); + } +} + +[Script] // 1214890 - Cycle of Hatred +class spell_dh_cycle_of_hatred_remove_stacks : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CycleOfHatredCooldownReduction); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Aura aura = GetTarget().GetAura(SpellIds.CycleOfHatredCooldownReduction); + if (aura != null) + aura.SetStackAmount(1); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 258887 - Cycle of Hatred +class spell_dh_cycle_of_hatred_talent : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CycleOfHatredCooldownReduction); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.CycleOfHatredCooldownReduction, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.CycleOfHatredCooldownReduction); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // Called by 212084 - Fel Devastation +class spell_dh_darkglare_boon : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (!ValidateSpellInfo(SpellIds.DarkglareBoonEnergize, SpellIds.FelDevastation) + || !ValidateSpellEffect((SpellIds.DarkglareBoon, 3))) + return false; + + SpellInfo darkglareBoon = Global.SpellMgr.GetSpellInfo(SpellIds.DarkglareBoon, Difficulty.None); + return darkglareBoon.GetEffect(0).CalcValue() < darkglareBoon.GetEffect(1).CalcValue() + && darkglareBoon.GetEffect(2).CalcValue() < darkglareBoon.GetEffect(3).CalcValue(); + } + + public override bool Load() + { + return GetUnitOwner().HasAura(SpellIds.DarkglareBoon); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // Tooltip mentions "fully channelled" being a requirement but ingame it always reduces cooldown and energizes, even when manually cancelled + //if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + // return; + + Unit target = GetTarget(); + Aura darkglareBoon = target.GetAura(SpellIds.DarkglareBoon); + + uint unused = 0; + TimeSpan cooldown = TimeSpan.Zero; + TimeSpan categoryCooldown = TimeSpan.Zero; + SpellHistory.GetCooldownDurations(GetSpellInfo(), 0, ref cooldown, ref unused, ref categoryCooldown); + int reductionPct = RandomHelper.IRand(darkglareBoon.GetEffect(0).GetAmount(), darkglareBoon.GetEffect(1).GetAmount()); + TimeSpan cooldownReduction = TimeSpan.FromSeconds(MathFunctions.CalculatePct(MathF.Max((float)cooldown.TotalMilliseconds, (float)categoryCooldown.TotalMilliseconds), reductionPct)); + + int energizeValue = RandomHelper.IRand(darkglareBoon.GetEffect(2).GetAmount(), darkglareBoon.GetEffect(3).GetAmount()); + + target.GetSpellHistory().ModifyCooldown(SpellIds.FelDevastation, -cooldownReduction); + + target.CastSpell(target, SpellIds.DarkglareBoonEnergize, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.FirstBlood); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, energizeValue) } + }); + } + + public override void Register() + { + OnEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 209426 - Darkness +class spell_dh_darkness : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + // Set absorbtion amount to unlimited + amount = -1; + } + + void Absorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + AuraEffect chanceEffect = GetEffect(1); + if (chanceEffect != null) + if (RandomHelper.randChance(chanceEffect.GetAmount())) + absorbAmount = dmgInfo.GetDamage(); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + OnEffectAbsorb.Add(new(Absorb, 0)); + } +} + +// 196718 - Darkness +[Script] // Id: 6615 +class areatrigger_dh_darkness : AreaTriggerAI +{ + SpellInfo _absorbAuraInfo; + + public areatrigger_dh_darkness(AreaTrigger areaTrigger) : base(areaTrigger) + { + _absorbAuraInfo = Global.SpellMgr.GetSpellInfo(SpellIds.DarknessAbsorb, Difficulty.None); + } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster == null || caster.IsValidAssistTarget(unit, _absorbAuraInfo)) + return; + + caster.CastSpell(unit, SpellIds.DarknessAbsorb, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.Duration, at.GetDuration()) } + }); + } + + public override void OnUnitExit(Unit unit) + { + unit.RemoveAura(SpellIds.DarknessAbsorb, at.GetCasterGUID()); + } +} + +[Script] // 203819 - Demon Spikes +class spell_dh_deflecting_spikes : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DeflectingSpikes) + && ValidateSpellEffect((spellInfo.Id, 0)) + && spellInfo.GetEffect(0).IsAura(AuraType.ModParryPercent); + } + + void HandleParryChance(ref WorldObject target) + { + if (!GetCaster().HasAura(SpellIds.DeflectingSpikes)) + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(HandleParryChance, 0, Targets.UnitCaster)); + } +} + +// 213410 - Demonic (attached to 212084 - Fel Devastation and 198013 - Eye Beam) +[Script("spell_dh_demonic_havoc", SpellIds.MetamorphosisTransform)] +[Script("spell_dh_demonic_vengeance", SpellIds.MetamorphosisVengeanceTransform)] +class spell_dh_demonic(uint transformSpellId) : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(transformSpellId) + && ValidateSpellEffect((SpellIds.Demonic, 0)) + && Global.SpellMgr.GetSpellInfo(SpellIds.Demonic, Difficulty.None).GetEffect(0).IsAura(); + } + + public override bool Load() + { + return GetCaster().HasAuraEffect(SpellIds.Demonic, 0); + } + + void TriggerMetamorphosis() + { + Unit caster = GetCaster(); + AuraEffect demonic = caster.GetAuraEffect(SpellIds.Demonic, 0); + if (demonic == null) + return; + + int duration = demonic.GetAmount() + GetSpell().GetChannelDuration(); + Aura aura = caster.GetAura(transformSpellId); + if (aura != null) + { + aura.SetMaxDuration(aura.GetDuration() + duration); + aura.SetDuration(aura.GetMaxDuration()); + return; } - void DecideFirstTarget(List targetList) + SpellCastTargets targets = new(); + targets.SetUnitTarget(caster); + + Spell spell = new Spell(caster, Global.SpellMgr.GetSpellInfo(transformSpellId, Difficulty.None), + TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + ObjectGuid.Empty, GetSpell().m_castId); + spell.m_SpellVisual.SpellXSpellVisualID = 0; + spell.m_SpellVisual.ScriptVisualID = 0; + spell.SetSpellValue(new(SpellValueMod.Duration, duration)); + spell.Prepare(targets); + } + + + public override void Register() + { + AfterCast.Add(new(TriggerMetamorphosis)); + } +} + +[Script] // 203720 - Demon Spikes +class spell_dh_demon_spikes : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DemonSpikes); + } + + void HandleArmor(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.DemonSpikes, new CastSpellExtraArgs() { - if (targetList.Empty()) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleArmor, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 258860 - Essence Break +class spell_dh_essence_break : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EssenceBreakDebuff); + } + + void HandleDebuff(uint effIndex) + { + Unit caster = GetCaster(); + + var targets = new CastSpellTargetArg(GetHitUnit()); + // debuff application is slightly delayed on official servers (after animation fully finishes playing) + caster.m_Events.AddEventAtOffset(() => + { + if (targets.Targets == null) return; - Aura aura = GetCaster().GetAura(SpellIds.FirstBlood); - if (aura == null) - return; + targets.Targets.Update(caster); - ObjectGuid firstTargetGUID = ObjectGuid.Empty; - ObjectGuid selectedTarget = GetCaster().GetTarget(); + caster.CastSpell(targets, SpellIds.EssenceBreakDebuff, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + }, TimeSpan.FromSeconds(300)); + } - // Prefer the selected target if he is one of the enemies - if (targetList.Count > 1 && !selectedTarget.IsEmpty()) + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDebuff, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 198013 - Eye Beam +class spell_dh_eye_beam : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EyeBeamDamage); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(null, SpellIds.EyeBeamDamage, new CastSpellExtraArgs() { - var obj = targetList.Find(obj => obj.GetGUID() == selectedTarget); - if (obj != null) - firstTargetGUID = obj.GetGUID(); - } - - if (firstTargetGUID.IsEmpty()) - firstTargetGUID = targetList[0].GetGUID(); - - spell_dh_first_blood script = aura.GetScript(); - if (script != null) - script.SetFirstTarget(firstTargetGUID); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(DecideFirstTarget, 0, Targets.UnitSrcAreaEnemy)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); } - // 199552 - Blade Dance - // 200685 - Blade Dance - // 210153 - Death Sweep - [Script] // 210155 - Death Sweep - class spell_dh_blade_dance_damage : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FirstBlood); - } + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); + } +} - void HandleHitTarget() - { - int damage = GetHitDamage(); +[Script] // Called by 228477 - Soul Cleave +class spell_dh_feast_of_souls : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FeastOfSouls, SpellIds.FeastOfSoulsPeriodicHeal); + } - AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.FirstBlood, 0); - if (aurEff != null) + public override bool Load() + { + return GetCaster().HasAura(SpellIds.FeastOfSouls); + } + + void HandleHeal() + { + GetCaster().CastSpell(GetCaster(), SpellIds.FeastOfSoulsPeriodicHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleHeal)); + } +} + +[Script] // 212084 - Fel Devastation +class spell_dh_fel_devastation : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FelDevastationHeal); + } + + void HandlePeriodicEffect(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.FelDevastationHeal, new CastSpellExtraArgs() { - spell_dh_first_blood script = aurEff.GetBase().GetScript(); - if (script != null) - if (GetHitUnit().GetGUID() == script.GetFirstTarget()) - MathFunctions.AddPct(ref damage, aurEff.GetAmount()); - } - - SetHitDamage(damage); - } - - public override void Register() - { - OnHit.Add(new(HandleHitTarget)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); } - [Script("areatrigger_dh_sigil_of_silence", SpellIds.SigilOfSilenceAoe)] - [Script("areatrigger_dh_sigil_of_misery", SpellIds.SigilOfMiseryAoe)] - [Script("areatrigger_dh_sigil_of_flame", SpellIds.SigilOfFlameAoe)] - class areatrigger_dh_generic_sigil : AreaTriggerAI + public override void Register() { - uint _trigger; + OnEffectPeriodic.Add(new(HandlePeriodicEffect, 0, AuraType.PeriodicTriggerSpell)); + } +} - public areatrigger_dh_generic_sigil(AreaTrigger at, uint trigger) : base(at) - { - _trigger = trigger; - } - - public override void OnRemove() - { - Unit caster = at.GetCaster(); - if (caster != null) - caster.CastSpell(at.GetPosition(), _trigger); - } +[Script] // Called by 258920 - Immolation Aura +class spell_dh_fel_flame_fortification : AuraScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.FelFlameFortificationTalent, SpellIds.FelFlameFortificationModDamage); } - [Script] // 208673 - Sigil of Chains - class spell_dh_sigil_of_chains : SpellScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SigilOfChainsSlow, SpellIds.SigilOfChainsGrip); - } + return GetUnitOwner().HasAura(SpellIds.FelFlameFortificationTalent); + } - void HandleEffectHitTarget(uint effIndex) + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.FelFlameFortificationModDamage, new CastSpellExtraArgs() { - WorldLocation loc = GetExplTargetDest(); - if (loc != null) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff, + OriginalCastId = aurEff.GetBase().GetCastId() + }); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.FelFlameFortificationModDamage); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnApply, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 232893 - Felblade +class spell_dh_felblade : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FelbladeCharge); + } + + void HandleCharge(uint effIndex) + { + uint spellToCast = GetCaster().IsWithinMeleeRange(GetHitUnit()) ? SpellIds.FelbladeDamage : SpellIds.FelbladeCharge; + GetCaster().CastSpell(GetHitUnit(), spellToCast, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleCharge, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 213241 - Felblade Charge +class spell_dh_felblade_charge : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FelbladeDamage); + } + + void HandleDamage(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.FelbladeDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDamage, 0, SpellEffectName.Charge)); + } +} + +// 203557 - Felblade (Vengeance cooldow reset proc aura) +[Script] // 236167 - Felblade (Havoc cooldow reset proc aura) +class spell_dh_felblade_cooldown_reset_proc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Felblade); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ResetCooldown(SpellIds.Felblade, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 204021 - Fiery Brand +class spell_dh_fiery_brand : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FieryBrandDebuffRank1, SpellIds.FieryBrandDebuffRank2, SpellIds.FieryBrandRank2); + } + + void HandleDamage(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), GetCaster().HasAura(SpellIds.FieryBrandRank2) ? SpellIds.FieryBrandDebuffRank2 : SpellIds.FieryBrandDebuffRank1, + new CastSpellExtraArgs() { - GetCaster().CastSpell(GetHitUnit(), SpellIds.SigilOfChainsSlow, true); - GetHitUnit().CastSpell(loc.GetPosition(), SpellIds.SigilOfChainsGrip, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } - [Script] // 202138 - Sigil of Chains - class areatrigger_dh_sigil_of_chains : AreaTriggerAI + public override void Register() { - public areatrigger_dh_sigil_of_chains(AreaTrigger at) : base(at) { } + OnEffectHitTarget.Add(new(HandleDamage, 1, SpellEffectName.SchoolDamage)); + } +} - public override void OnRemove() +[Script] // 206416 - First Blood +class spell_dh_first_blood : AuraScript +{ + ObjectGuid _firstTargetGuid; + + public ObjectGuid GetFirstTarget() { return _firstTargetGuid; } + + public void SetFirstTarget(ObjectGuid targetGuid) { _firstTargetGuid = targetGuid; } + + public override void Register() + { + } +} + +[Script] // Called by 198013 - Eye Beam +class spell_dh_furious_gaze : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FuriousGaze, SpellIds.FuriousGazeBuff); + } + + public override bool Load() + { + return GetUnitOwner().HasAura(SpellIds.FuriousGaze); + } + + void HandleAfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.FuriousGazeBuff, new CastSpellExtraArgs() { - Unit caster = at.GetCaster(); - if (caster != null) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleAfterRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +// 342817 - Glaive Tempest +[Script] // Id - 21832 +class at_dh_glaive_tempest(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TaskScheduler _scheduler = new(); + + public override void OnCreate(Spell creatingSpell) + { + _scheduler.Schedule(TimeSpan.Zero, task => { - caster.CastSpell(at.GetPosition(), SpellIds.SigilOfChainsVisual); - caster.CastSpell(at.GetPosition(), SpellIds.SigilOfChainsTargetSelect); - } - } - } - - [Script] // 131347 - Glide - class spell_dh_glide : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlideKnockback, SpellIds.GlideDuration, SpellIds.VengefulRetreatTrigger, SpellIds.FelRush); - } - - SpellCastResult CheckCast() - { - Unit caster = GetCaster(); - if (caster.IsMounted() || caster.GetVehicleBase() != null) - return SpellCastResult.DontReport; - - if (!caster.IsFalling()) - return SpellCastResult.NotOnGround; - - return SpellCastResult.SpellCastOk; - } - - void HandleCast() - { - Player caster = GetCaster().ToPlayer(); - if (caster == null) - return; - - caster.CastSpell(caster, SpellIds.GlideKnockback, true); - caster.CastSpell(caster, SpellIds.GlideDuration, true); - - caster.GetSpellHistory().StartCooldown(SpellMgr.GetSpellInfo(SpellIds.VengefulRetreatTrigger, GetCastDifficulty()), 0, null, false, TimeSpan.FromMilliseconds(250)); - caster.GetSpellHistory().StartCooldown(SpellMgr.GetSpellInfo(SpellIds.FelRush, GetCastDifficulty()), 0, null, false, TimeSpan.FromMilliseconds(250)); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - BeforeCast.Add(new(HandleCast)); - } - } - - [Script] // 131347 - Glide - class spell_dh_glide_AuraScript : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlideDuration); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAura(SpellIds.GlideDuration); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.FeatherFall, AuraEffectHandleModes.Real)); - } - } - - [Script] // 197154 - Glide - class spell_dh_glide_timer : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Glide); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAura(SpellIds.Glide); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 391166 - Soul Furnace - class spell_dh_soul_furnace : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SoulFurnaceDamageBuff); - } - - void CalculateSpellMod(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetStackAmount() == GetAura().CalcMaxStackAmount()) - { - GetTarget().CastSpell(GetTarget(), SpellIds.SoulFurnaceDamageBuff, true); - Remove(); - } - } - - public override void Register() - { - AfterEffectApply.Add(new(CalculateSpellMod, 0, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); - } - } - - [Script] // 339424 - Soul Furnace - class spell_dh_soul_furnace_conduit : AuraScript - { - void CalculateSpellMod(AuraEffect aurEff, ref SpellModifier spellMod) - { - if (aurEff.GetAmount() == 10) - { - if (spellMod == null) + TimeSpan period = TimeSpan.FromSeconds(500); // TimeSpan.FromSeconds(500), affected by haste + Unit caster = at.GetCaster(); + if (caster != null) { - spellMod = new SpellModifierByClassMask(GetAura()); - spellMod.op = SpellModOp.HealingAndDamage; - spellMod.type = SpellModType.Pct; - spellMod.spellId = GetId(); - (spellMod as SpellModifierByClassMask).mask = new FlagArray128(0x80000000); - (spellMod as SpellModifierByClassMask).value = GetEffect(1).GetAmount() + 1; + period *= caster.m_unitData.ModHaste; + caster.CastSpell(at.GetPosition(), SpellIds.GlaiveTempest, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + caster.CastSpell(at.GetPosition(), SpellIds.GlaiveTempest, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); } - } + task.Repeat(period); + }); + } + + public override void OnUpdate(uint diff) + { + _scheduler.Update(diff); + } +} + +[Script] // Called by 162264 - Metamorphosis +class spell_dh_inner_demon : AuraScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.InnerDemonTalent, SpellIds.InnerDemonBuff); + } + + public override bool Load() + { + return GetUnitOwner().HasAura(SpellIds.InnerDemonTalent); // This spell has a proc, but is just a copypaste from spell 390145 (also don't have a TimeSpan.FromSeconds(5) cooldown) + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.InnerDemonBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + }); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnApply, 0, AuraType.Transform, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +// 390139 - Inner Demon +[Script] // Id - 26749 +class at_dh_inner_demon(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnInitialize() + { + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(at.GetSpellId(), Difficulty.None); + if (spellInfo == null) + return; + + Unit caster = at.GetCaster(); + if (caster == null) + return; + + Position destPos = at.GetFirstCollisionPosition(spellInfo.GetEffect(0).CalcValue(caster) + at.GetMaxSearchRadius(), at.GetRelativeAngle(caster)); + PathGenerator path = new(at); + + path.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false); + + at.InitSplines(path.GetPath()); + } + + public override void OnRemove() + { + Unit caster = at.GetCaster(); + if (caster != null) + caster.CastSpell(caster.GetPosition(), SpellIds.InnerDemonDamage, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } +} + +[Script] // 388118 - Know Your Enemy +class spell_dh_know_your_enemy : AuraScript +{ + void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + AuraEffect amountHolder = GetEffect(1); + if (amountHolder != null) + { + float critChanceDone = GetUnitOwner().GetUnitCriticalChanceDone(WeaponAttackType.BaseAttack); + amount = (int)MathFunctions.CalculatePct(critChanceDone, amountHolder.GetAmount()); + } + } + + void UpdatePeriodic(AuraEffect aurEff) + { + AuraEffect bonus = GetEffect(0); + if (bonus != null) + bonus.RecalculateAmount(aurEff); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalcAmount, 0, AuraType.ModCritDamageBonus)); + OnEffectPeriodic.Add(new(UpdatePeriodic, 1, AuraType.PeriodicDummy)); + } +} + +[Script] // 209258 - Last Resort +class spell_dh_last_resort : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UncontainedFel, SpellIds.MetamorphosisVengeanceTransform) + && ValidateSpellEffect((spellInfo.Id, 1)); + } + + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + Unit target = GetTarget(); + if (target.HasAura(SpellIds.UncontainedFel)) + { + absorbAmount = 0; + return; } - public override void Register() + PreventDefaultAction(); + + CastSpellExtraArgs castArgs = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError | TriggerCastFlags.IgnoreSpellAndCategoryCD; + + target.CastSpell(target, SpellIds.MetamorphosisVengeanceTransform, castArgs); + target.CastSpell(target, SpellIds.UncontainedFel, castArgs); + + target.SetHealth(target.CountPctFromMaxHealth(GetEffectInfo(1).CalcValue(target))); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + } +} + +[Script] // 452414 - Monster Rising +class spell_dh_monster_rising : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MonsterRisingAgility, SpellIds.MetamorphosisTransform, SpellIds.MetamorphosisVengeanceTransform); + } + + void HandlePeriodic(AuraEffect aurEff) + { + Unit target = GetTarget(); + AuraApplication statBuff = target.GetAuraApplication(SpellIds.MonsterRisingAgility); + + if (target.HasAura(SpellIds.MetamorphosisTransform) || target.HasAura(SpellIds.MetamorphosisVengeanceTransform)) { - DoEffectCalcSpellMod.Add(new(CalculateSpellMod, 0, AuraType.Dummy)); + if (statBuff != null) + target.RemoveAura(statBuff); } + else if (statBuff == null) + { + target.CastSpell(target, SpellIds.MonsterRisingAgility, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDummy)); + } +} + +// 188499 - Blade Dance +[Script] // 210152 - Death Sweep +class spell_dh_blade_dance : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FirstBlood); + } + + void DecideFirstTarget(List targetList) + { + if (targetList.Empty()) + return; + + Aura aura = GetCaster().GetAura(SpellIds.FirstBlood); + if (aura == null) + return; + + ObjectGuid firstTargetGuid = ObjectGuid.Empty; + ObjectGuid selectedTarget = GetCaster().GetTarget(); + + // Prefer the selected target if he is one of the enemies + if (targetList.Count > 1 && !selectedTarget.IsEmpty()) + { + var it = targetList.Find(obj => obj.GetGUID() == selectedTarget); + if (it != null) + firstTargetGuid = it.GetGUID(); + } + + if (firstTargetGuid.IsEmpty()) + firstTargetGuid = targetList.FirstOrDefault().GetGUID(); + + spell_dh_first_blood script = aura.GetScript(); + if (script != null) + script.SetFirstTarget(firstTargetGuid); + } + + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(DecideFirstTarget, 0, Targets.UnitSrcAreaEnemy)); + } +} + +// 199552 - Blade Dance +// 200685 - Blade Dance +// 210153 - Death Sweep +[Script] // 210155 - Death Sweep +class spell_dh_blade_dance_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FirstBlood); + } + + void HandleHitTarget() + { + int damage = GetHitDamage(); + + AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.FirstBlood, 0); + if (aurEff != null) + { + spell_dh_first_blood script = aurEff.GetBase().GetScript(); + if (script != null && GetHitUnit().GetGUID() == script.GetFirstTarget()) + MathFunctions.AddPct(ref damage, aurEff.GetAmount()); + } + + SetHitDamage(damage); + } + + public override void Register() + { + OnHit.Add(new(HandleHitTarget)); + } +} + +[Script] // 131347 - Glide +class spell_dh_glide : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlideKnockback, SpellIds.GlideDuration, SpellIds.VengefulRetreatTrigger, SpellIds.FelRush); + } + + SpellCastResult CheckCast() + { + Unit caster = GetCaster(); + if (caster.IsMounted() || caster.GetVehicleBase() != null) + return SpellCastResult.DontReport; + + if (!caster.IsFalling()) + return SpellCastResult.NotOnGround; + + return SpellCastResult.SpellCastOk; + } + + void HandleCast() + { + Player caster = GetCaster().ToPlayer(); + if (caster == null) + return; + + caster.CastSpell(caster, SpellIds.GlideKnockback, true); + caster.CastSpell(caster, SpellIds.GlideDuration, true); + + caster.GetSpellHistory().StartCooldown(Global.SpellMgr.GetSpellInfo(SpellIds.VengefulRetreatTrigger, GetCastDifficulty()), 0, null, false, TimeSpan.FromSeconds(250)); + caster.GetSpellHistory().StartCooldown(Global.SpellMgr.GetSpellInfo(SpellIds.FelRush, GetCastDifficulty()), 0, null, false, TimeSpan.FromSeconds(250)); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + BeforeCast.Add(new(HandleCast)); + } +} + +[Script] // 131347 - Glide +class spell_dh_glide_AuraScript : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlideDuration); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAura(SpellIds.GlideDuration); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.FeatherFall, AuraEffectHandleModes.Real)); + } +} + +[Script] // 197154 - Glide +class spell_dh_glide_timer : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Glide); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAura(SpellIds.Glide); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // Called by 162264 - Metamorphosis +class spell_dh_restless_hunter : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RestlessHunterTalent, SpellIds.RestlessHunterBuff, SpellIds.FelRush) + && CliDB.SpellCategoryStorage.HasRecord(Global.SpellMgr.GetSpellInfo(SpellIds.FelRush, Difficulty.None).ChargeCategoryId); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.RestlessHunterTalent); + } + + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + + target.CastSpell(target, SpellIds.RestlessHunterBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + + target.GetSpellHistory().RestoreCharge(Global.SpellMgr.GetSpellInfo(SpellIds.FelRush, GetCastDifficulty()).ChargeCategoryId); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Transform, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +[Script] // 388116 - Shattered Destiny +class spell_dh_shattered_destiny : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MetamorphosisTransform) + && ValidateSpellEffect((spellInfo.Id, 1)) + && spellInfo.GetEffect(0).IsAura() + && spellInfo.GetEffect(1).IsAura(); + } + + bool CheckFurySpent(ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + if (!eventInfo.GetActor().HasAura(SpellIds.MetamorphosisTransform)) + return false; + + _furySpent += procSpell.GetPowerTypeCostAmount(PowerType.Fury).GetValueOrDefault(0); + return _furySpent >= GetEffect(1).GetAmount(); + } + + void HandleProc(ProcEventInfo eventInfo) + { + Aura metamorphosis = GetTarget().GetAura(SpellIds.MetamorphosisTransform); + if (metamorphosis == null) + return; + + int requiredFuryAmount = GetEffect(1).GetAmount(); + metamorphosis.SetDuration(metamorphosis.GetDuration() + _furySpent / requiredFuryAmount * GetEffect(0).GetAmount()); + _furySpent %= requiredFuryAmount; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckFurySpent)); + OnProc.Add(new(HandleProc)); + } + + + int _furySpent = 0; +} + +[Script] // 391166 - Soul Furnace +class spell_dh_soul_furnace : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SoulFurnaceDamageBuff); + } + + void CalculateSpellMod(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetStackAmount() == GetAura().CalcMaxStackAmount()) + { + GetTarget().CastSpell(GetTarget(), SpellIds.SoulFurnaceDamageBuff, true); + Remove(); + } + } + + public override void Register() + { + AfterEffectApply.Add(new(CalculateSpellMod, 0, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +[Script] // 339424 - Soul Furnace +class spell_dh_soul_furnace_conduit : AuraScript +{ + void CalculateSpellMod(AuraEffect aurEff, ref SpellModifier spellMod) + { + if (aurEff.GetAmount() == 10) + { + if (spellMod == null) + { + spellMod = new SpellModifierByClassMask(GetAura()); + spellMod.op = SpellModOp.HealingAndDamage; + spellMod.type = SpellModType.Pct; + spellMod.spellId = GetId(); + ((SpellModifierByClassMask)spellMod).mask = new FlagArray128(0x80000000); + ((SpellModifierByClassMask)spellMod).value = GetEffect(1).GetAmount() + 1; + } + } + } + + public override void Register() + { + DoEffectCalcSpellMod.Add(new(CalculateSpellMod, 0, AuraType.Dummy)); + } +} + +// 202138 - Sigil of Chains +// 204596 - Sigil of Flame +// 207684 - Sigil of Misery +// 202137 - Sigil of Silence +//template +[Script("areatrigger_dh_sigil_of_chains", SpellIds.SigilOfChainsTargetSelect, SpellIds.SigilOfChainsVisual)] +[Script("areatrigger_dh_sigil_of_flame", SpellIds.SigilOfFlameAoe, SpellIds.SigilOfFlameVisual)] +[Script("areatrigger_dh_sigil_of_silence", SpellIds.SigilOfSilenceAoe)] +[Script("areatrigger_dh_sigil_of_misery", SpellIds.SigilOfMiseryAoe)] +class areatrigger_dh_generic_sigil(AreaTrigger areaTrigger, uint triggerSpellId, uint triggerSpellId2 = 0): AreaTriggerAI(areaTrigger) +{ + public override void OnRemove() + { + Unit caster = at.GetCaster(); + if (caster != null) + { + caster.CastSpell(at.GetPosition(), triggerSpellId); + if (triggerSpellId2 != 0) + caster.CastSpell(at.GetPosition(), triggerSpellId2); + } + } +} + +[Script] // 208673 - Sigil of Chains +class spell_dh_sigil_of_chains : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SigilOfChainsSlow, SpellIds.SigilOfChainsGrip); + } + + void HandleEffectHitTarget(uint effIndex) + { + WorldLocation loc = GetExplTargetDest(); + if (loc != null) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.SigilOfChainsSlow, true); + GetHitUnit().CastSpell(loc.GetPosition(), SpellIds.SigilOfChainsGrip, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); + } +} + +[Script] // Called by 204598 - Sigil of Flame +class spell_dh_student_of_suffering : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StudentOfSufferingTalent, SpellIds.StudentOfSufferingAura); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.StudentOfSufferingTalent); + } + + void HandleStudentOfSuffering() + { + GetCaster().CastSpell(GetCaster(), SpellIds.StudentOfSufferingAura, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + + public override void Register() + { + AfterCast.Add(new(HandleStudentOfSuffering)); + } +} + +[Script] // Called by 198793 - Vengeful Retreat +class spell_dh_tactical_retreat : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TacticalRetreatTalent, SpellIds.TacticalRetreatEnergize); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.TacticalRetreatTalent); + } + + void Energize() + { + GetCaster().CastSpell(GetCaster(), SpellIds.TacticalRetreatEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(Energize)); + } +} + +[Script] // 444931 - Unhindered Assault +class spell_dh_unhindered_assault : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Felblade); + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ResetCooldown(SpellIds.Felblade, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); + } +} + +[Script] // 198813 - Vengeful Retreat +class spell_dh_vengeful_retreat_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VengefulBonds); + } + + void HandleVengefulBonds(List targets) + { + if (!GetCaster().HasAura(SpellIds.VengefulBonds)) + targets.Clear(); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(HandleVengefulBonds, 0, Targets.UnitSrcAreaEnemy)); + } +} + +[Script] // 452409 - Violent Transformation +class spell_dh_violent_transformation : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SigilOfFlame, SpellIds.VengeanceDemonHunter, SpellIds.FelDevastation, SpellIds.ImmolationAura); + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + target.GetSpellHistory().RestoreCharge(Global.SpellMgr.GetSpellInfo(SpellIds.SigilOfFlame, GetCastDifficulty()).ChargeCategoryId); + + if (target.HasAura(SpellIds.VengeanceDemonHunter)) + target.GetSpellHistory().ResetCooldown(SpellIds.FelDevastation, true); + else + target.GetSpellHistory().RestoreCharge(Global.SpellMgr.GetSpellInfo(SpellIds.ImmolationAura, GetCastDifficulty()).ChargeCategoryId); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); } } \ No newline at end of file diff --git a/Source/Scripts/Spells/Druid.cs b/Source/Scripts/Spells/Druid.cs index b216281fe..46418a6f7 100644 --- a/Source/Scripts/Spells/Druid.cs +++ b/Source/Scripts/Spells/Druid.cs @@ -1,2245 +1,2560 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Framework.Dynamic; +using Game.AI; +using Game.DataStorage; using Game.Entities; using Game.Maps; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using static Global; -namespace Scripts.Spells.Druid +namespace Scripts.Spells.Druid; + +struct SpellIds { - struct SpellIds + public const uint Abundance = 207383; + public const uint AbundanceEffect = 207640; + public const uint AstralCommunionEnergize = 450599; + public const uint AstralCommunionTalent = 450598; + public const uint AstralSmolderDamage = 394061; + public const uint BalanceT10_Bonus = 70718; + public const uint BalanceT10_BonusProc = 70721; + public const uint BearForm = 5487; + public const uint BlessingOfCenarius = 40452; + public const uint BlessingOfElune = 40446; + public const uint BlessingOfRemulos = 40445; + public const uint BlessingOfTheClaw = 28750; + public const uint BloodFrenzyAura = 203962; + public const uint BloodFrenzyRageGain = 203961; + public const uint BramblesDamageAura = 213709; + public const uint BramblesPassive = 203953; + public const uint BramblesReflect = 203958; + public const uint BristlingFurGainRage = 204031; + public const uint CatForm = 768; + public const uint Cultivation = 200390; + public const uint CultivationHeal = 200389; + public const uint CuriousBramblepatch = 330670; + public const uint Dreamstate = 450346; + public const uint DreamOfCenarius = 372152; + public const uint DreamOfCenariusCooldown = 372523; + public const uint EarthwardenAura = 203975; + public const uint EclipseDummy = 79577; + public const uint EclipseLunarAura = 48518; + public const uint EclipseLunarSpellCnt = 326055; + public const uint EclipseOoc = 329910; + public const uint EclipseSolarAura = 48517; + public const uint EclipseSolarSpellCnt = 326053; + public const uint EclipseVisualLunar = 93431; + public const uint EclipseVisualSolar = 93430; + public const uint EfflorescenceAura = 81262; + public const uint EfflorescenceHeal = 81269; + public const uint EmbraceOfTheDreamEffect = 392146; + public const uint EmbraceOfTheDreamHeal = 392147; + public const uint EntanglingRoots = 339; + public const uint Exhilarate = 28742; + public const uint FormAquaticPassive = 276012; + public const uint FormAquatic = 1066; + public const uint FormFlight = 33943; + public const uint FormStag = 165961; + public const uint FormSwiftFlight = 40120; + public const uint FormsTrinketBear = 37340; + public const uint FormsTrinketCat = 37341; + public const uint FormsTrinketMoonkin = 37343; + public const uint FormsTrinketNone = 37344; + public const uint FormsTrinketTree = 37342; + public const uint FullMoon = 274283; + public const uint GalacticGuardianAura = 213708; + public const uint Germination = 155675; + public const uint GlyphOfStars = 114301; + public const uint GlyphOfStarsVisual = 114302; + public const uint GoreProc = 93622; + public const uint Growl = 6795; + public const uint HalfMoon = 274282; + public const uint HalfMoonOverride = 274297; + public const uint IdolOfFeralShadows = 34241; + public const uint IdolOfWorship = 60774; + public const uint Incarnation = 117679; + public const uint IncarnationKingOfTheJungle = 102543; + public const uint IncarnationTreeOfLife = 33891; + public const uint InnerPeace = 197073; + public const uint Innervate = 29166; + public const uint InnervateRank2 = 326228; + public const uint Infusion = 37238; + public const uint Languish = 71023; + public const uint LifebloomFinalHeal = 33778; + public const uint LunarBeamHeal = 204069; + public const uint LunarBeamDamage = 414613; + public const uint LunarInspirationOverride = 155627; + public const uint Mangle = 33917; + public const uint MangleTalent = 231064; + public const uint MassEntanglement = 102359; + public const uint MoonfireDamage = 164812; + public const uint NaturesGraceTalent = 450347; + public const uint NewMoon = 274281; + public const uint NewMoonOverride = 274295; + public const uint PowerOfTheArchdruid = 392302; + public const uint Prowl = 5215; + public const uint Regrowth = 8936; + public const uint Rejuvenation = 774; + public const uint RejuvenationGermination = 155777; + public const uint RejuvenationT10_Proc = 70691; + public const uint RestorationT10_2PBonus = 70658; + public const uint SavageRoar = 62071; + public const uint ShootingStars = 202342; + public const uint ShootingStarsDamage = 202497; + public const uint SkullBashCharge = 221514; + public const uint SkullBashInterrupt = 93985; + public const uint SpringBlossoms = 207385; + public const uint SpringBlossomsHeal = 207386; + public const uint StarBurst = 356474; + public const uint SunfireDamage = 164815; + public const uint SurvivalInstincts = 50322; + public const uint TravelForm = 783; + public const uint TreeOfLife = 33891; + public const uint ThrashBear = 77758; + public const uint ThrashBearAura = 192090; + public const uint ThrashCat = 106830; + public const uint UmbralEmbrace = 393763; + public const uint UmbralInspirationTalent = 450418; + public const uint UmbralInspirationAura = 450419; + public const uint UrsocsFuryShield = 372505; + public const uint YserasGiftHealParty = 145110; + public const uint YserasGiftHealSelf = 145109; +} + +// 774 - Rejuvenation +[Script] // 155777 - Rejuvenation (Germination) +class spell_dru_abundance : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) { - public const uint Abundance = 207383; - public const uint AbundanceEffect = 207640; - public const uint AstralCommunionEnergize = 450599; - public const uint AstralCommunionTalent = 450598; - public const uint AstralSmolderDamage = 394061; - public const uint BalanceT10Bonus = 70718; - public const uint BalanceT10BonusProc = 70721; - public const uint BearForm = 5487; - public const uint BlessingOfCenarius = 40452; - public const uint BlessingOfElune = 40446; - public const uint BlessingOfRemulos = 40445; - public const uint BlessingOfTheClaw = 28750; - public const uint BloodFrenzyAura = 203962; - public const uint BloodFrenzyRageGain = 203961; - public const uint BramblesDamageAura = 213709; - public const uint BramblesPassive = 203953; - public const uint BramblesReflect = 203958; - public const uint BristlingFurGainRage = 204031; - public const uint CatForm = 768; - public const uint Cultivation = 200390; - public const uint CultivationHeal = 200389; - public const uint CuriousBramblepatch = 330670; - public const uint EarthwardenAura = 203975; - public const uint EclipseDummy = 79577; - public const uint EclipseLunarAura = 48518; - public const uint EclipseLunarSpellCnt = 326055; - public const uint EclipseOoc = 329910; - public const uint EclipseSolarAura = 48517; - public const uint EclipseSolarSpellCnt = 326053; - public const uint EclipseVisualLunar = 93431; - public const uint EclipseVisualSolar = 93430; - public const uint EfflorescenceAura = 81262; - public const uint EfflorescenceHeal = 81269; - public const uint EmbraceOfTheDreamEffect = 392146; - public const uint EmbraceOfTheDreamHeal = 392147; - public const uint EntanglingRoots = 339; - public const uint Exhilarate = 28742; - public const uint FormAquaticPassive = 276012; - public const uint FormAquatic = 1066; - public const uint FormFlight = 33943; - public const uint FormStag = 165961; - public const uint FormSwiftFlight = 40120; - public const uint FormsTrinketBear = 37340; - public const uint FormsTrinketCat = 37341; - public const uint FormsTrinketMoonkin = 37343; - public const uint FormsTrinketNone = 37344; - public const uint FormsTrinketTree = 37342; - public const uint FullMoon = 274283; - public const uint GalacticGuardianAura = 213708; - public const uint Germination = 155675; - public const uint GlyphOfStars = 114301; - public const uint GlyphOfStarsVisual = 114302; - public const uint GoreProc = 93622; - public const uint Growl = 6795; - public const uint HalfMoon = 274282; - public const uint HalfMoonOverride = 274297; - public const uint IdolOfFeralShadows = 34241; - public const uint IdolOfWorship = 60774; - public const uint Incarnation = 117679; - public const uint IncarnationKingOfTheJungle = 102543; - public const uint IncarnationTreeOfLife = 33891; - public const uint InnerPeace = 197073; - public const uint Innervate = 29166; - public const uint InnervateRank2 = 326228; - public const uint Infusion = 37238; - public const uint Languish = 71023; - public const uint LifebloomFinalHeal = 33778; - public const uint LunarInspirationOverride = 155627; - public const uint Mangle = 33917; - public const uint MassEntanglement = 102359; - public const uint MoonfireDamage = 164812; - public const uint NewMoon = 274281; - public const uint NewMoonOverride = 274295; - public const uint PowerOfTheArchdruid = 392302; - public const uint Prowl = 5215; - public const uint Regrowth = 8936; - public const uint Rejuvenation = 774; - public const uint RejuvenationGermination = 155777; - public const uint RejuvenationT10Proc = 70691; - public const uint RestorationT102PBonus = 70658; - public const uint SavageRoar = 62071; - public const uint ShootingStars = 202342; - public const uint ShootingStarsDamage = 202497; - public const uint SkullBashCharge = 221514; - public const uint SkullBashInterrupt = 93985; - public const uint SpringBlossoms = 207385; - public const uint SpringBlossomsHeal = 207386; - public const uint StarBurst = 356474; - public const uint SunfireDamage = 164815; - public const uint SurvivalInstincts = 50322; - public const uint TravelForm = 783; - public const uint TreeOfLife = 33891; - public const uint ThrashBear = 77758; - public const uint ThrashBearAura = 192090; - public const uint ThrashCat = 106830; - public const uint YserasGiftHealParty = 145110; - public const uint YserasGiftHealSelf = 145109; + return ValidateSpellInfo(SpellIds.Abundance, SpellIds.AbundanceEffect); } - // 774 - Rejuvenation - [Script] // 155777 - Rejuvenation (Germination) - class spell_dru_abundance : AuraScript + void HandleOnApplyOrReapply(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) + Unit caster = GetCaster(); + if (caster == null || !caster.HasAura(SpellIds.Abundance)) + return; + + // Note: caster only casts Abundance when first applied on the target, otherwise that given stack is refreshed. + if ((mode & AuraEffectHandleModes.Real) != 0) + caster.CastSpell(caster, SpellIds.AbundanceEffect, new CastSpellExtraArgs().SetTriggeringAura(aurEff)); + else { - return ValidateSpellInfo(SpellIds.Abundance, SpellIds.AbundanceEffect); - } - - void HandleOnApplyOrReapply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster == null || !caster.HasAura(SpellIds.Abundance)) - return; - - // Note: caster only casts Abundance when first applied on the target, otherwise that given stack is refreshed. - if (mode.HasFlag(AuraEffectHandleModes.Real)) - caster.CastSpell(caster, SpellIds.AbundanceEffect, new CastSpellExtraArgs().SetTriggeringAura(aurEff)); - else - { - Aura abundanceAura = caster.GetAura(SpellIds.AbundanceEffect); - if (abundanceAura != null) - abundanceAura.RefreshDuration(); - } - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - Aura abundanceEffect = caster.GetAura(SpellIds.AbundanceEffect); - if (abundanceEffect != null) - abundanceEffect.ModStackAmount(-1); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleOnApplyOrReapply, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.RealOrReapplyMask)); - AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.Real)); + Aura abundanceAura = caster.GetAura(SpellIds.AbundanceEffect); + if (abundanceAura != null) + abundanceAura.RefreshDuration(); } } - // 102560 - Incarnation: Chosen of Elune - // 194223 - Celestial Alignment - // 383410 - Celestial Alignment - [Script] // 390414 - Incarnation: Chosen of Elune - class spell_dru_astral_communion_celestial_alignment : SpellScript + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AstralCommunionTalent, SpellIds.AstralCommunionEnergize); - } + Unit caster = GetCaster(); + if (caster == null) + return; - public override bool Load() - { - return GetCaster().HasAura(SpellIds.AstralCommunionTalent); - } - - void Energize() - { - GetCaster().CastSpell(GetCaster(), SpellIds.AstralCommunionEnergize, new CastSpellExtraArgs() - .SetTriggeringSpell(GetSpell()) - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); - } - - public override void Register() - { - AfterCast.Add(new(Energize)); - } - } - - [Script] // 394058 - Astral Smolder - class spell_dru_astral_smolder : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.AstralSmolderDamage, 0)) - && SpellMgr.GetSpellInfo(SpellIds.AstralSmolderDamage, Difficulty.None).GetMaxTicks() != 0; - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - SpellInfo astralSmolderDmg = SpellMgr.GetSpellInfo(SpellIds.AstralSmolderDamage, GetCastDifficulty()); - int pct = aurEff.GetAmount(); - - int amount = (int)(MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), pct) / astralSmolderDmg.GetMaxTicks()); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.AstralSmolderDamage, args); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + Aura abundanceEffect = caster.GetAura(SpellIds.AbundanceEffect); + if (abundanceEffect != null) + abundanceEffect.ModStackAmount(-1); } - [Script] // 22812 - Barkskin - class spell_dru_barkskin : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BramblesPassive); - } + AfterEffectApply.Add(new(HandleOnApplyOrReapply, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.RealOrReapplyMask)); + AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.Real)); + } +} - void HandlePeriodic(AuraEffect aurEff) +// 102560 - Incarnation: Chosen of Elune +// 194223 - Celestial Alignment +// 383410 - Celestial Alignment +[Script] // 390414 - Incarnation: Chosen of Elune +class spell_dru_astral_communion_celestial_alignment : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AstralCommunionTalent, SpellIds.AstralCommunionEnergize); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.AstralCommunionTalent); + } + + void Energize() + { + GetCaster().CastSpell(GetCaster(), SpellIds.AstralCommunionEnergize, new CastSpellExtraArgs() + .SetTriggeringSpell(GetSpell()) + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); + } + + public override void Register() + { + AfterCast.Add(new(Energize)); + } +} + +[Script] // 394058 - Astral Smolder +class spell_dru_astral_smolder : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.AstralSmolderDamage, 0)) + && Global.SpellMgr.GetSpellInfo(SpellIds.AstralSmolderDamage, Difficulty.None).GetMaxTicks() != 0; + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() != null; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + SpellInfo astralSmolderDmg = Global.SpellMgr.GetSpellInfo(SpellIds.AstralSmolderDamage, GetCastDifficulty()); + int pct = aurEff.GetAmount(); + + int amount = (int)(MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), pct) / astralSmolderDmg.GetMaxTicks()); + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, amount); + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.AstralSmolderDamage, args); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 22812 - Barkskin +class spell_dru_barkskin : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BramblesPassive); + } + + void HandlePeriodic(AuraEffect aurEff) + { + Unit target = GetTarget(); + if (target.HasAura(SpellIds.BramblesPassive)) + target.CastSpell(target, SpellIds.BramblesDamageAura, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodic, 2, AuraType.PeriodicDummy)); + } +} + +[Script] // 50334 - Berserk +class spell_dru_berserk : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BearForm, SpellIds.Mangle, SpellIds.ThrashBear, SpellIds.Growl); + } + + void HandleOnCast() + { + // Change into correct form + if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.BearForm) + GetCaster().CastSpell(GetCaster(), SpellIds.BearForm, true); + } + + void ResetCooldowns() + { + GetCaster().GetSpellHistory().ResetCooldown(SpellIds.Mangle); + GetCaster().GetSpellHistory().ResetCooldown(SpellIds.ThrashBear); + GetCaster().GetSpellHistory().ResetCooldown(SpellIds.Growl); + } + + public override void Register() + { + BeforeCast.Add(new(HandleOnCast)); + AfterCast.Add(new(ResetCooldowns)); + } +} + +[Script] // 203953 - Brambles - SpellBramblesPassive +class spell_dru_brambles : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BramblesReflect, SpellIds.BramblesDamageAura); + } + + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + // Prevent Removal + PreventDefaultAction(); + } + + void HandleAfterAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + // reflect back damage to the attacker + Unit target = GetTarget(); + Unit attacker = dmgInfo.GetAttacker(); + if (attacker != null) + target.CastSpell(attacker, SpellIds.BramblesReflect, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, (int)absorbAmount)); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + AfterEffectAbsorb.Add(new(HandleAfterAbsorb, 0)); + } +} + +[Script] // 155835 - Bristling Fur +class spell_dru_bristling_fur : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BristlingFurGainRage); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + // BristlingFurRage = 100 * Damage / MaxHealth. + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo != null) { Unit target = GetTarget(); - if (target.HasAura(SpellIds.BramblesPassive)) - target.CastSpell(target, SpellIds.BramblesDamageAura, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodic, 2, AuraType.PeriodicDummy)); + int rage = (int)(target.GetMaxPower(PowerType.Rage) * (float)damageInfo.GetDamage() / (float)target.GetMaxHealth()); + if (rage > 0) + target.CastSpell(target, SpellIds.BristlingFurGainRage, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, rage)); } } - [Script] // 50334 - Berserk - class spell_dru_berserk : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BearForm, SpellIds.Mangle, SpellIds.ThrashBear, SpellIds.Growl); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - void HandleOnCast() - { - // Change into cat form - if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.BearForm) - GetCaster().CastSpell(GetCaster(), SpellIds.BearForm, true); - } - - void ResetCooldowns() - { - GetCaster().GetSpellHistory().ResetCooldown(SpellIds.Mangle); - GetCaster().GetSpellHistory().ResetCooldown(SpellIds.ThrashBear); - GetCaster().GetSpellHistory().ResetCooldown(SpellIds.Growl); - } - - public override void Register() - { - BeforeCast.Add(new(HandleOnCast)); - AfterCast.Add(new(ResetCooldowns)); - } +[Script] // 768 - CatForm - SpellCatForm +class spell_dru_cat_form : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Prowl); } - [Script] // 203953 - Brambles - SpellBramblesPassive - class spell_dru_brambles : AuraScript + void HandleAfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BramblesReflect, SpellIds.BramblesDamageAura); - } - - void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - // Prevent Removal - PreventDefaultAction(); - } - - void HandleAfterAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - // reflect back damage to the attacker - Unit target = GetTarget(); - Unit attacker = dmgInfo.GetAttacker(); - if (attacker != null) - target.CastSpell(attacker, SpellIds.BramblesReflect, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, (int)absorbAmount)); - } - - public override void Register() - { - OnEffectAbsorb.Add(new(HandleAbsorb, 0)); - AfterEffectAbsorb.Add(new(HandleAfterAbsorb, 0)); - } + GetTarget().RemoveOwnedAura(SpellIds.Prowl); } - [Script] // 155835 - Bristling Fur - class spell_dru_bristling_fur : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BristlingFurGainRage); - } + AfterEffectRemove.Add(new(HandleAfterRemove, 0, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - // BristlingFurRage = 100 * Damage / MaxHealth. - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo != null) - { - Unit target = GetTarget(); - uint rage = (uint)(target.GetMaxPower(PowerType.Rage) * (float)damageInfo.GetDamage() / (float)target.GetMaxHealth()); - if (rage > 0) - target.CastSpell(target, SpellIds.BristlingFurGainRage, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, (int)rage)); - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +// 102560 - Incarnation: Chosen of Elune +// 194223 - Celestial Alignment +// 383410 - Celestial Alignment +[Script] // 390414 - Incarnation: Chosen of Elune +class spell_dru_celestial_alignment : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EclipseSolarAura, SpellIds.EclipseLunarAura, SpellIds.EclipseVisualSolar, SpellIds.EclipseVisualLunar); } - [Script] // 768 - CatForm - SpellCatForm - class spell_dru_cat_form : AuraScript + void TriggerEclipses() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Prowl); - } + Unit caster = GetCaster(); + CastSpellExtraArgs args = new(); + args.SetTriggeringSpell(GetSpell()); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); - void HandleAfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveOwnedAura(SpellIds.Prowl); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleAfterRemove, 0, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); - } + caster.CastSpell(caster, SpellIds.EclipseSolarAura, args); + caster.CastSpell(caster, SpellIds.EclipseLunarAura, args); + caster.CastSpell(caster, SpellIds.EclipseVisualSolar, args); + caster.CastSpell(caster, SpellIds.EclipseVisualLunar, args); } - // 102560 - Incarnation: Chosen of Elune - // 194223 - Celestial Alignment - // 383410 - Celestial Alignment - // 390414 - Incarnation: Chosen of Elune - [Script] - class spell_dru_celestial_alignment : SpellScript + + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EclipseSolarAura, SpellIds.EclipseLunarAura, SpellIds.EclipseVisualSolar, SpellIds.EclipseVisualLunar); - } + AfterCast.Add(new(TriggerEclipses)); + } +} - void TriggerEclipses() - { - Unit caster = GetCaster(); - CastSpellExtraArgs args = new(); - args.SetTriggeringSpell(GetSpell()); - args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); - - caster.CastSpell(caster, SpellIds.EclipseSolarAura, args); - caster.CastSpell(caster, SpellIds.EclipseLunarAura, args); - caster.CastSpell(caster, SpellIds.EclipseVisualSolar, args); - caster.CastSpell(caster, SpellIds.EclipseVisualLunar, args); - } - - public override void Register() - { - AfterCast.Add(new(TriggerEclipses)); - } +// 774 - Rejuvenation +[Script] // 155777 - Rejuventation (Germination) +class spell_dru_cultivation : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CultivationHeal) + && ValidateSpellEffect((SpellIds.Cultivation, 0)); } - // 774 - Rejuvenation - [Script] // 155777 - Rejuventation (Germination) - class spell_dru_cultivation : AuraScript + void HandleOnTick(AuraEffect aurEff) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CultivationHeal) && ValidateSpellEffect((SpellIds.Cultivation, 0)); - } + Unit caster = GetCaster(); + if (caster == null) + return; - void HandleOnTick(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - Unit target = GetTarget(); - AuraEffect cultivationEffect = caster.GetAuraEffect(SpellIds.Cultivation, 0); - if (cultivationEffect != null) - if (target.HealthBelowPct(cultivationEffect.GetAmount())) - caster.CastSpell(target, SpellIds.CultivationHeal, new CastSpellExtraArgs().SetTriggeringAura(aurEff)); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleOnTick, 0, AuraType.PeriodicHeal)); - } + Unit target = GetTarget(); + AuraEffect cultivationEffect = caster.GetAuraEffect(SpellIds.Cultivation, 0); + if (cultivationEffect != null) + if (target.HealthBelowPct(cultivationEffect.GetAmount())) + caster.CastSpell(target, SpellIds.CultivationHeal, new CastSpellExtraArgs().SetTriggeringAura(aurEff)); } - [Script] // 1850 - Dash - class spell_dru_dash : AuraScript + public override void Register() { - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - // do not set speed if not in cat form - if (GetUnitOwner().GetShapeshiftForm() != ShapeShiftForm.CatForm) - amount = 0; - } + OnEffectPeriodic.Add(new(HandleOnTick, 0, AuraType.PeriodicHeal)); + } +} - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModIncreaseSpeed)); - } +[Script] // 1850 - Dash +class spell_dru_dash : AuraScript +{ + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + // do not set speed if not in cat form + if (GetUnitOwner().GetShapeshiftForm() != ShapeShiftForm.CatForm) + amount = 0; } - [Script] // 203974 - Earthwarden - class spell_dru_earthwarden : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ThrashCat, SpellIds.ThrashBear, SpellIds.EarthwardenAura); - } + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModIncreaseSpeed)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit target = GetTarget(); - target.CastSpell(target, SpellIds.EarthwardenAura, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 372119 - Dream of Cenarius (Guardian) +class spell_dru_dream_of_cenarius_guardian : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DreamOfCenarius, SpellIds.DreamOfCenariusCooldown); } - class spell_dru_eclipse_common + bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public static void SetSpellCount(Unit unitOwner, uint spellId, uint amount) - { - Aura aura = unitOwner.GetAura(spellId); - if (aura == null) - unitOwner.CastSpell(unitOwner, spellId, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, (int)amount)); - else - aura.SetStackAmount((byte)amount); - } + if (GetUnitOwner().HasAura(SpellIds.DreamOfCenariusCooldown)) + return false; + + return RandomHelper.randChance(GetUnitOwner().GetUnitCriticalChanceDone(WeaponAttackType.BaseAttack)); } - [Script] // 48517 Eclipse (Solar) + 48518 Eclipse (Lunar) - class spell_dru_eclipse_AuraScript : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseDummy); - } + Unit target = GetTarget(); + CastSpellExtraArgs args = new(); + args.SetTriggeringAura(aurEff); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); - void HandleRemoved(AuraEffect aurEff, AuraEffectHandleModes mode) - { - AuraEffect auraEffDummy = GetTarget().GetAuraEffect(SpellIds.EclipseDummy, 0); - if (auraEffDummy == null) - return; - - uint spellId = GetSpellInfo().Id == SpellIds.EclipseSolarAura ? SpellIds.EclipseLunarSpellCnt : SpellIds.EclipseSolarSpellCnt; - spell_dru_eclipse_common.SetSpellCount(GetTarget(), spellId, (uint)auraEffDummy.GetAmount()); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleRemoved, 0, AuraType.AddPctModifier, AuraEffectHandleModes.Real)); - } + target.CastSpell(target, SpellIds.DreamOfCenarius, args); + target.CastSpell(target, SpellIds.DreamOfCenariusCooldown, args); } - [Script] // 79577 - Eclipse - SpellEclipseDummy - class spell_dru_eclipse_dummy : AuraScript + public override void Register() { - class InitializeEclipseCountersEvent : BasicEvent - { - Unit _owner; - uint _count; + DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - public InitializeEclipseCountersEvent(Unit owner, uint count) - { - _owner = owner; - _count = count; - } - - public override bool Execute(ulong e_time, uint p_time) - { - spell_dru_eclipse_common.SetSpellCount(_owner, SpellIds.EclipseSolarSpellCnt, _count); - spell_dru_eclipse_common.SetSpellCount(_owner, SpellIds.EclipseLunarSpellCnt, _count); - return true; - } - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarAura, SpellIds.EclipseLunarAura, SpellIds.AstralCommunionTalent, SpellIds.AstralCommunionEnergize); - } - - void HandleProc(ProcEventInfo eventInfo) - { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo != null) - { - if (spellInfo.SpellFamilyFlags & new FlagArray128(0x4, 0x0, 0x0, 0x0)) // Starfire - OnSpellCast(SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarAura); - else if (spellInfo.SpellFamilyFlags & new FlagArray128(0x1, 0x0, 0x0, 0x0)) // Wrath - OnSpellCast(SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarAura); - } - } - - void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // counters are applied with a delay - GetTarget().m_Events.AddEventAtOffset(new InitializeEclipseCountersEvent(GetTarget(), (uint)aurEff.GetAmount()), TimeSpan.FromSeconds(1)); - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAura(SpellIds.EclipseSolarSpellCnt); - GetTarget().RemoveAura(SpellIds.EclipseLunarSpellCnt); - } - - void OnOwnerOutOfCombat(bool isNowInCombat) - { - if (!isNowInCombat) - GetTarget().CastSpell(GetTarget(), SpellIds.EclipseOoc, TriggerCastFlags.FullMask); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnProc.Add(new(HandleProc)); - OnEnterLeaveCombat.Add(new(OnOwnerOutOfCombat)); - } - - void OnSpellCast(uint cntSpellId, uint otherCntSpellId, uint eclipseAuraSpellId) - { - Unit target = GetTarget(); - Aura aura = target.GetAura(cntSpellId); - if (aura != null) - { - uint remaining = aura.GetStackAmount(); - if (remaining == 0) - return; - - if (remaining > 1) - aura.SetStackAmount((byte)(remaining - 1)); - else - { - // cast eclipse - target.CastSpell(target, eclipseAuraSpellId, TriggerCastFlags.FullMask); - - if (target.HasAura(SpellIds.AstralCommunionTalent)) - target.CastSpell(target, SpellIds.AstralCommunionEnergize, true); - - // Remove stacks from other one as well - // reset remaining power on other spellId - target.RemoveAura(cntSpellId); - target.RemoveAura(otherCntSpellId); - } - } - } +[Script] // 203974 - Earthwarden +class spell_dru_earthwarden : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ThrashCat, SpellIds.ThrashBear, SpellIds.EarthwardenAura); } - [Script] // 329910 - Eclipse out of combat - SpellEclipseOoc - class spell_dru_eclipse_ooc : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EclipseDummy, SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarSpellCnt); - } - - void Tick(AuraEffect aurEff) - { - Unit owner = GetTarget(); - AuraEffect auraEffDummy = owner.GetAuraEffect(SpellIds.EclipseDummy, 0); - if (auraEffDummy == null) - return; - - if (!owner.IsInCombat() && (!owner.HasAura(SpellIds.EclipseSolarSpellCnt) || !owner.HasAura(SpellIds.EclipseLunarSpellCnt))) - { - // Restore 2 stacks to each spell when out of combat - spell_dru_eclipse_common.SetSpellCount(owner, SpellIds.EclipseSolarSpellCnt, (uint)auraEffDummy.GetAmount()); - spell_dru_eclipse_common.SetSpellCount(owner, SpellIds.EclipseLunarSpellCnt, (uint)auraEffDummy.GetAmount()); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(Tick, 0, AuraType.PeriodicDummy)); - } + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.EarthwardenAura, true); } - [Script] // 145205 - Efflorescence - class spell_dru_efflorescence : SpellScript + public override void Register() { - void RemoveOldAreaTrigger(uint effIndex) - { - // if caster has any Efflorescence areatrigger, we Remove it. - GetCaster().RemoveAreaTrigger(GetSpellInfo().Id); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - void InitSummon() - { - foreach (var summonedObject in GetSpell().GetExecuteLogEffect(SpellEffectName.Summon).GenericVictimTargets) - { - Unit summon = ObjectAccessor.GetCreature(GetCaster(), summonedObject.Victim); - if (summon != null) - summon.CastSpell(summon, SpellIds.EfflorescenceAura, - new CastSpellExtraArgs().SetTriggeringSpell(GetSpell())); - } - } +class spell_dru_eclipse_common +{ + public static void SetSpellCount(Unit unitOwner, uint spellId, uint amount) + { + Aura aura = unitOwner.GetAura(spellId); + if (aura == null) + unitOwner.CastSpell(unitOwner, spellId, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, (int)amount)); + else + aura.SetStackAmount((byte)amount); + } +} - public override void Register() - { - OnEffectLaunch.Add(new(RemoveOldAreaTrigger, 2, SpellEffectName.CreateAreaTrigger)); - AfterCast.Add(new(InitSummon)); - } +[Script] // 48517 Eclipse (Solar) + 48518 Eclipse (Lunar) +class spell_dru_eclipse_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseDummy); } - [Script] // 81262 - Efflorescence (Dummy) - class spell_dru_efflorescence_dummy : AuraScript + void HandleRemoved(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EfflorescenceHeal); - } + AuraEffect auraEffDummy = GetTarget().GetAuraEffect(SpellIds.EclipseDummy, 0); + if (auraEffDummy == null) + return; - void HandlePeriodicDummy(AuraEffect aurEff) - { - Unit target = GetTarget(); - Unit summoner = target.GetOwner(); - if (summoner == null) - return; - - summoner.CastSpell(target, SpellIds.EfflorescenceHeal, TriggerCastFlags.DontReportCastError); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodicDummy, 0, AuraType.PeriodicDummy)); - } + uint spellId = GetSpellInfo().Id == SpellIds.EclipseSolarAura ? SpellIds.EclipseLunarSpellCnt : SpellIds.EclipseSolarSpellCnt; + spell_dru_eclipse_common.SetSpellCount(GetTarget(), spellId, (uint)auraEffDummy.GetAmount()); } - [Script] // 81269 - Efflorescence (Heal) - class spell_dru_efflorescence_heal : SpellScript + public override void Register() { - void FilterTargets(List targets) - { - // Efflorescence became a smart heal which prioritizes players and their pets in their group before any unit outside their group. - SelectRandomInjuredTargets(targets, 3, true, GetCaster()); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - } + AfterEffectRemove.Add(new(HandleRemoved, 0, AuraType.AddPctModifier, AuraEffectHandleModes.Real)); } +} - [Script] // 392124 - Embrace of the Dream - class spell_dru_embrace_of_the_dream : AuraScript +[Script] // 79577 - Eclipse - SpellIds.EclipseDummy +class spell_dru_eclipse_dummy : AuraScript +{ + class InitializeEclipseCountersEvent(Unit owner, uint count) : BasicEvent() { - public override bool Validate(SpellInfo spellInfo) + public override bool Execute(ulong e_time, uint p_time) { - return ValidateSpellInfo(SpellIds.EmbraceOfTheDreamEffect) - && ValidateSpellEffect((spellInfo.Id, 2)); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(GetEffectInfo(2).CalcValue(GetCaster())); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().CastSpell(GetTarget(), SpellIds.EmbraceOfTheDreamEffect, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringAura(aurEff) - .SetTriggeringSpell(eventInfo.GetProcSpell())); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 392146 - Embrace of the Dream (Selector) - class spell_dru_embrace_of_the_dream_effect : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EmbraceOfTheDreamHeal, SpellIds.Regrowth, SpellIds.Rejuvenation, SpellIds.RejuvenationGermination); - } - - void FilterTargets(List targets) - { - targets.RemoveAll(target => target.ToUnit()?.GetAuraEffect(AuraType.PeriodicHeal, SpellFamilyNames.Druid, new FlagArray128(0x50, 0, 0, 0), GetCaster().GetGUID()) == null); - } - - void HandleEffect(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.EmbraceOfTheDreamHeal, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(GetSpell())); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - OnEffectHitTarget.Add(new(HandleEffect, 0, SpellEffectName.Dummy)); - } - } - - // 339 - Entangling Roots - [Script] // 102359 - Mass Entanglement - class spell_dru_entangling_roots : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CuriousBramblepatch); - } - - void HandleCuriousBramblepatch(ref WorldObject target) - { - if (!GetCaster().HasAura(SpellIds.CuriousBramblepatch)) - target = null; - } - - void HandleCuriousBramblepatchAOE(List targets) - { - if (!GetCaster().HasAura(SpellIds.CuriousBramblepatch)) - targets.Clear(); - } - - public override void Register() - { - OnObjectTargetSelect.Add(new(HandleCuriousBramblepatch, 1, Targets.UnitTargetEnemy)); - if (m_scriptSpellId == SpellIds.MassEntanglement) - OnObjectAreaTargetSelect.Add(new(HandleCuriousBramblepatchAOE, 1, Targets.UnitDestAreaEnemy)); - } - } - - [Script] - class spell_dru_entangling_roots_AuraScript : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EntanglingRoots, SpellIds.MassEntanglement); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo != null) - { - // dont subtract dmg caused by roots from dmg required to break root - if (spellInfo.Id == SpellIds.EntanglingRoots || spellInfo.Id == SpellIds.MassEntanglement) - return false; - } + spell_dru_eclipse_common.SetSpellCount(owner, SpellIds.EclipseSolarSpellCnt, count); + spell_dru_eclipse_common.SetSpellCount(owner, SpellIds.EclipseLunarSpellCnt, count); return true; } + } - public override void Register() + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarAura, SpellIds.EclipseLunarAura, SpellIds.AstralCommunionTalent, SpellIds.AstralCommunionEnergize); + } + + void HandleProc(ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo != null) { - DoCheckProc.Add(new(CheckProc)); + if (spellInfo.SpellFamilyFlags & new FlagArray128(0x4, 0x0, 0x0, 0x0)) // Starfire + OnSpellCast(SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarAura); + else if (spellInfo.SpellFamilyFlags & new FlagArray128(0x1, 0x0, 0x0, 0x0)) // Wrath + OnSpellCast(SpellIds.EclipseLunarSpellCnt, SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarAura); } } - [Script] // 22568 - Ferocious Bite - class spell_dru_ferocious_bite : SpellScript + void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - float _damageMultiplier; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.IncarnationKingOfTheJungle, 1)); - } - - void HandleHitTargetBurn(uint effIndex) - { - int newValue = (int)((float)(GetEffectValue()) * _damageMultiplier); - SetEffectValue(newValue); - } - - void HandleHitTargetDmg(uint effIndex) - { - int newValue = (int)((float)(GetHitDamage()) * (1.0f + _damageMultiplier)); - SetHitDamage(newValue); - } - - void HandleLaunchTarget(uint effIndex) - { - Unit caster = GetCaster(); - - int maxExtraConsumedPower = GetEffectValue(); - - AuraEffect auraEffect = caster.GetAuraEffect(SpellIds.IncarnationKingOfTheJungle, 1); - if (auraEffect != null) - { - float multiplier = 1.0f + (float)(auraEffect.GetAmount()) / 100.0f; - maxExtraConsumedPower = (int)((float)(maxExtraConsumedPower) * multiplier); - SetEffectValue(maxExtraConsumedPower); - } - - _damageMultiplier = Math.Min(caster.GetPower(PowerType.Energy), maxExtraConsumedPower) / maxExtraConsumedPower; - } - - public override void Register() - { - OnEffectLaunchTarget.Add(new(HandleLaunchTarget, 1, SpellEffectName.PowerBurn)); - OnEffectHitTarget.Add(new(HandleHitTargetBurn, 1, SpellEffectName.PowerBurn)); - OnEffectHitTarget.Add(new(HandleHitTargetDmg, 0, SpellEffectName.SchoolDamage)); - } + // counters are applied with a delay + GetTarget().m_Events.AddEventAtOffset(new InitializeEclipseCountersEvent(GetTarget(), (uint)aurEff.GetAmount()), TimeSpan.FromSeconds(1)); } - [Script] // 37336 - Druid Forms Trinket - class spell_dru_forms_trinket : AuraScript + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FormsTrinketBear, SpellIds.FormsTrinketCat, SpellIds.FormsTrinketMoonkin, SpellIds.FormsTrinketNone, SpellIds.FormsTrinketTree); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - Unit target = eventInfo.GetActor(); - - return target.GetShapeshiftForm() switch - { - ShapeShiftForm.BearForm or ShapeShiftForm.DireBearForm or ShapeShiftForm.CatForm or ShapeShiftForm.MoonkinForm or ShapeShiftForm.None or ShapeShiftForm.TreeOfLife => true, - _ => false - }; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit target = eventInfo.GetActor(); - - uint triggerspell = target.GetShapeshiftForm() switch - { - ShapeShiftForm.BearForm or ShapeShiftForm.DireBearForm => SpellIds.FormsTrinketBear, - ShapeShiftForm.CatForm => SpellIds.FormsTrinketCat, - ShapeShiftForm.MoonkinForm => SpellIds.FormsTrinketMoonkin, - ShapeShiftForm.None => SpellIds.FormsTrinketNone, - ShapeShiftForm.TreeOfLife => SpellIds.FormsTrinketTree, - _ => 0 - }; - - if (triggerspell != 0) - target.CastSpell(target, triggerspell, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } + GetTarget().RemoveAura(SpellIds.EclipseSolarSpellCnt); + GetTarget().RemoveAura(SpellIds.EclipseLunarSpellCnt); } - [Script] // 203964 - Galactic Guardian - class spell_dru_galactic_guardian : AuraScript + void OnOwnerOutOfCombat(bool isNowInCombat) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GalacticGuardianAura); - } + if (!isNowInCombat) + GetTarget().CastSpell(GetTarget(), SpellIds.EclipseOoc, TriggerCastFlags.FullMask); + } - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + public override void Register() + { + AfterEffectApply.Add(new(HandleApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnProc.Add(new(HandleProc)); + OnEnterLeaveCombat.Add(new(OnOwnerOutOfCombat)); + } + + + void OnSpellCast(uint cntSpellId, uint otherCntSpellId, uint eclipseAuraSpellId) + { + Unit target = GetTarget(); + Aura aura = target.GetAura(cntSpellId); + if (aura != null) { - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo != null) + uint remaining = aura.GetStackAmount(); + if (remaining == 0) + return; + + if (remaining > 1) + aura.SetStackAmount((byte)(remaining - 1)); + else { - Unit target = GetTarget(); + // cast eclipse + target.CastSpell(target, eclipseAuraSpellId, TriggerCastFlags.FullMask); - // free automatic moonfire on target - target.CastSpell(damageInfo.GetVictim(), SpellIds.MoonfireDamage, true); + if (target.HasAura(SpellIds.AstralCommunionTalent)) + target.CastSpell(target, SpellIds.AstralCommunionEnergize, true); - // Cast aura - target.CastSpell(damageInfo.GetVictim(), SpellIds.GalacticGuardianAura, true); + // Remove stacks from other one as well + // reset remaining power on other spellId + target.RemoveAura(cntSpellId); + target.RemoveAura(otherCntSpellId); } } + } +} - public override void Register() +[Script] // 329910 - Eclipse out of combat - SpellEclipseOoc +class spell_dru_eclipse_ooc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EclipseDummy, SpellIds.EclipseSolarSpellCnt, SpellIds.EclipseLunarSpellCnt); + } + + void Tick(AuraEffect aurEff) + { + Unit owner = GetTarget(); + AuraEffect auraEffDummy = owner.GetAuraEffect(SpellIds.EclipseDummy, 0); + if (auraEffDummy == null) + return; + + if (!owner.IsInCombat() && (!owner.HasAura(SpellIds.EclipseSolarSpellCnt) || !owner.HasAura(SpellIds.EclipseLunarSpellCnt))) { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + // Restore 2 stacks to each spell when out of combat + spell_dru_eclipse_common.SetSpellCount(owner, SpellIds.EclipseSolarSpellCnt, (uint)auraEffDummy.GetAmount()); + spell_dru_eclipse_common.SetSpellCount(owner, SpellIds.EclipseLunarSpellCnt, (uint)auraEffDummy.GetAmount()); } } - [Script] // 774 - Rejuvenation - class spell_dru_germination : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnEffectPeriodic.Add(new(Tick, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 145205 - Efflorescence +class spell_dru_efflorescence : SpellScript +{ + void RemoveOldAreaTrigger(uint effIndex) + { + // if caster has any Efflorescence areatrigger, we remove it. + GetCaster().RemoveAreaTrigger(GetSpellInfo().Id); + } + + void InitSummon() + { + foreach (var summonedObject in GetSpell().GetExecuteLogEffect(SpellEffectName.Summon).GenericVictimTargets) { - return ValidateSpellInfo(SpellIds.Rejuvenation, SpellIds.Germination, SpellIds.RejuvenationGermination); - } - - void PickRejuvenationVariant(ref WorldObject target) - { - Unit caster = GetCaster(); - - // Germination talent. - if (caster.HasAura(SpellIds.Germination)) - { - Unit unitTarget = target.ToUnit(); - Aura rejuvenationAura = unitTarget.GetAura(SpellIds.Rejuvenation, caster.GetGUID()); - Aura germinationAura = unitTarget.GetAura(SpellIds.RejuvenationGermination, caster.GetGUID()); - - // if target doesn't have Rejuventation, cast passes through. - if (rejuvenationAura == null) - return; - - // if target has Rejuvenation, but not Germination, or Germination has lower remaining duration than Rejuvenation, then cast Germination - if (germinationAura != null && germinationAura.GetDuration() >= rejuvenationAura.GetDuration()) - return; - - caster.CastSpell(target, SpellIds.RejuvenationGermination, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(GetSpell())); - - // prevent aura refresh (but cast must still happen to consume mana) - target = null; - } - } - - public override void Register() - { - OnObjectTargetSelect.Add(new(PickRejuvenationVariant, 0, Targets.UnitTargetAlly)); + Unit summon = ObjectAccessor.GetCreature(GetCaster(), summonedObject.Victim); + if (summon != null) + summon.CastSpell(summon, SpellIds.EfflorescenceAura, + new CastSpellExtraArgs().SetTriggeringSpell(GetSpell())); } } - [Script] // 24858 - Moonkin Form - class spell_dru_glyph_of_stars : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spell) + OnEffectLaunch.Add(new(RemoveOldAreaTrigger, 2, SpellEffectName.CreateAreaTrigger)); + AfterCast.Add(new(InitSummon)); + } +} + +[Script] // 81262 - Efflorescence (Dummy) +class spell_dru_efflorescence_dummy : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EfflorescenceHeal); + } + + void HandlePeriodicDummy(AuraEffect aurEff) + { + Unit target = GetTarget(); + Unit summoner = target.GetOwner(); + if (summoner == null) + return; + + summoner.CastSpell(target, SpellIds.EfflorescenceHeal, TriggerCastFlags.DontReportCastError); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodicDummy, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 81269 - Efflorescence (Heal) +class spell_dru_efflorescence_heal : SpellScript +{ + void FilterTargets(List targets) + { + // Efflorescence became a smart heal which prioritizes players and their pets in their group before any unit outside their group. + SelectRandomInjuredTargets(targets, 3, true, GetCaster()); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +[Script] // 392124 - Embrace of the Dream +class spell_dru_embrace_of_the_dream : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EmbraceOfTheDreamEffect) + && ValidateSpellEffect((spellInfo.Id, 2)); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(GetEffectInfo(2).CalcValue(GetCaster())); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(GetTarget(), SpellIds.EmbraceOfTheDreamEffect, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringAura(aurEff) + .SetTriggeringSpell(eventInfo.GetProcSpell())); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 392146 - Embrace of the Dream (Selector) +class spell_dru_embrace_of_the_dream_effect : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EmbraceOfTheDreamHeal, SpellIds.Regrowth, SpellIds.Rejuvenation, SpellIds.RejuvenationGermination); + } + + void FilterTargets(List targets) + { + targets.RemoveAll(target => { - return ValidateSpellInfo(SpellIds.GlyphOfStars, SpellIds.GlyphOfStarsVisual); + Unit unitTarget = target.ToUnit(); + return unitTarget == null || unitTarget.GetAuraEffect(AuraType.PeriodicHeal, SpellFamilyNames.Druid, new FlagArray128(0x50, 0, 0, 0), GetCaster().GetGUID()) == null; + }); + } + + void HandleEffect(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.EmbraceOfTheDreamHeal, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); + } + + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + OnEffectHitTarget.Add(new(HandleEffect, 0, SpellEffectName.Dummy)); + } +} + +// 339 - Entangling Roots +[Script] // 102359 - Mass Entanglement +class spell_dru_entangling_roots : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CuriousBramblepatch); + } + + void HandleCuriousBramblepatch(ref WorldObject target) + { + if (!GetCaster().HasAura(SpellIds.CuriousBramblepatch)) + target = null; + } + + void HandleCuriousBramblepatchAoe(List targets) + { + if (!GetCaster().HasAura(SpellIds.CuriousBramblepatch)) + targets.Clear(); + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(HandleCuriousBramblepatch, 1, Targets.UnitTargetEnemy)); + if (m_scriptSpellId == SpellIds.MassEntanglement) + OnObjectAreaTargetSelect.Add(new(HandleCuriousBramblepatchAoe, 1, Targets.UnitDestAreaEnemy)); + } +} + +[Script] +class spell_dru_entangling_roots_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EntanglingRoots, SpellIds.MassEntanglement); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo != null) + { + // dont subtract dmg caused by roots from dmg required to break root + if (spellInfo.Id == SpellIds.EntanglingRoots || spellInfo.Id == SpellIds.MassEntanglement) + return false; + } + return true; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] // 22568 - Ferocious Bite +class spell_dru_ferocious_bite : SpellScript +{ + float _damageMultiplier; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.IncarnationKingOfTheJungle, 1)); + } + + void HandleHitTargetBurn(uint effIndex) + { + int newValue = (int)((float)GetEffectValue() * _damageMultiplier); + SetEffectValue(newValue); + } + + void HandleHitTargetDmg(uint effIndex) + { + int newValue = (int)((float)GetHitDamage() * (1.0f + _damageMultiplier)); + SetHitDamage(newValue); + } + + void HandleLaunchTarget(uint effIndex) + { + Unit caster = GetCaster(); + + int maxExtraConsumedPower = GetEffectValue(); + + AuraEffect auraEffect = caster.GetAuraEffect(SpellIds.IncarnationKingOfTheJungle, 1); + if (auraEffect != null) + { + float multiplier = 1.0f + (float)auraEffect.GetAmount() / 100.0f; + maxExtraConsumedPower = (int)((float)maxExtraConsumedPower * multiplier); + SetEffectValue(maxExtraConsumedPower); } - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + _damageMultiplier = MathF.Min(caster.GetPower(PowerType.Energy), maxExtraConsumedPower) / maxExtraConsumedPower; + } + + public override void Register() + { + OnEffectLaunchTarget.Add(new(HandleLaunchTarget, 1, SpellEffectName.PowerBurn)); + OnEffectHitTarget.Add(new(HandleHitTargetBurn, 1, SpellEffectName.PowerBurn)); + OnEffectHitTarget.Add(new(HandleHitTargetDmg, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 37336 - Druid Forms Trinket +class spell_dru_forms_trinket : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FormsTrinketBear, SpellIds.FormsTrinketCat, SpellIds.FormsTrinketMoonkin, SpellIds.FormsTrinketNone, SpellIds.FormsTrinketTree); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + Unit target = eventInfo.GetActor(); + + switch (target.GetShapeshiftForm()) + { + case ShapeShiftForm.BearForm: + case ShapeShiftForm.DireBearForm: + case ShapeShiftForm.CatForm: + case ShapeShiftForm.MoonkinForm: + case ShapeShiftForm.None: + case ShapeShiftForm.TreeOfLife: + return true; + default: + break; + } + + return false; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit target = eventInfo.GetActor(); + uint triggerspell = 0; + + switch (target.GetShapeshiftForm()) + { + case ShapeShiftForm.BearForm: + case ShapeShiftForm.DireBearForm: + triggerspell = SpellIds.FormsTrinketBear; + break; + case ShapeShiftForm.CatForm: + triggerspell = SpellIds.FormsTrinketCat; + break; + case ShapeShiftForm.MoonkinForm: + triggerspell = SpellIds.FormsTrinketMoonkin; + break; + case ShapeShiftForm.None: + triggerspell = SpellIds.FormsTrinketNone; + break; + case ShapeShiftForm.TreeOfLife: + triggerspell = SpellIds.FormsTrinketTree; + break; + default: + return; + } + + target.CastSpell(target, triggerspell, aurEff); + } + + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 203964 - Galactic Guardian +class spell_dru_galactic_guardian : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GalacticGuardianAura); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo != null) { Unit target = GetTarget(); - if (target.HasAura(SpellIds.GlyphOfStars)) - target.CastSpell(target, SpellIds.GlyphOfStarsVisual, true); - } - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.GlyphOfStarsVisual); - } + // free automatic moonfire on target + target.CastSpell(damageInfo.GetVictim(), SpellIds.MoonfireDamage, true); - public override void Register() - { - OnEffectApply.Add(new(OnApply, 1, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, 1, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); + // Cast aura + target.CastSpell(damageInfo.GetVictim(), SpellIds.GalacticGuardianAura, true); } } - [Script] // 210706 - Gore - class spell_dru_gore : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GoreProc, SpellIds.Mangle); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(aurEff.GetAmount()); - } +[Script] // 774 - Rejuvenation +class spell_dru_germination : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Rejuvenation, SpellIds.Germination, SpellIds.RejuvenationGermination); + } - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Unit owner = GetTarget(); - owner.CastSpell(owner, SpellIds.GoreProc); - owner.GetSpellHistory().ResetCooldown(SpellIds.Mangle, true); - } + void PickRejuvenationVariant(ref WorldObject target) + { + Unit caster = GetCaster(); - public override void Register() + // Germination talent. + if (caster.HasAura(SpellIds.Germination)) { - DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + Unit unitTarget = target.ToUnit(); + Aura rejuvenationAura = unitTarget.GetAura(SpellIds.Rejuvenation, caster.GetGUID()); + Aura germinationAura = unitTarget.GetAura(SpellIds.RejuvenationGermination, caster.GetGUID()); + + // if target doesn't have Rejuventation, cast passes through. + if (rejuvenationAura == null) + return; + + // if target has Rejuvenation, but not Germination, or Germination has lower remaining duration than Rejuvenation, then cast Germination + if (germinationAura != null && germinationAura.GetDuration() >= rejuvenationAura.GetDuration()) + return; + + caster.CastSpell(target, SpellIds.RejuvenationGermination, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); + + // prevent aura refresh (but cast must still happen to consume mana) + target = null; } } - [Script] // 99 - Incapacitating Roar - class spell_dru_incapacitating_roar : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BearForm); - } + OnObjectTargetSelect.Add(new(PickRejuvenationVariant, 0, Targets.UnitTargetAlly)); + } +} - void HandleOnCast() - { - if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.BearForm) - GetCaster().CastSpell(GetCaster(), SpellIds.BearForm, true); - } - - public override void Register() - { - BeforeCast.Add(new(HandleOnCast)); - } +[Script] // 24858 - Moonkin Form +class spell_dru_glyph_of_stars : AuraScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.GlyphOfStars, SpellIds.GlyphOfStarsVisual); } - [Script] // 29166 - Innervate - class spell_dru_innervate : SpellScript + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - SpellCastResult CheckCast() - { - Player target = GetExplTargetUnit()?.ToPlayer(); - if (target == null) - return SpellCastResult.BadTargets; - - var spec = target.GetPrimarySpecializationEntry(); - if (spec == null || spec.GetRole() != ChrSpecializationRole.Healer) - return SpellCastResult.BadTargets; - - return SpellCastResult.SpellCastOk; - } - - void HandleRank2() - { - Unit caster = GetCaster(); - if (caster != GetHitUnit()) - { - AuraEffect innervateR2 = caster.GetAuraEffect(SpellIds.InnervateRank2, 0); - if (innervateR2 != null) - caster.CastSpell(caster, SpellIds.Innervate, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnoreCastInProgress) - .SetTriggeringSpell(GetSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, -innervateR2.GetAmount())); - } - - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnHit.Add(new(HandleRank2)); - } + Unit target = GetTarget(); + if (target.HasAura(SpellIds.GlyphOfStars)) + target.CastSpell(target, SpellIds.GlyphOfStarsVisual, true); } - [Script] // 117679 - Incarnation (Passive) - class spell_dru_incarnation : AuraScript + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.IncarnationTreeOfLife); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.IncarnationTreeOfLife); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.IgnoreSpellCooldown, AuraEffectHandleModes.Real)); - } + GetTarget().RemoveAurasDueToSpell(SpellIds.GlyphOfStarsVisual); } - [Script] // 33891 - Incarnation: Tree of Life (Talent, Shapeshift) - class spell_dru_incarnation_tree_of_life : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Incarnation); - } + OnEffectApply.Add(new(OnApply, 1, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, 1, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); + } +} - void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (!GetTarget().HasAura(SpellIds.Incarnation)) - GetTarget().CastSpell(GetTarget(), SpellIds.Incarnation, true); - } - - public override void Register() - { - AfterEffectApply.Add(new(AfterApply, 2, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); - } +[Script] // 210706 - Gore +class spell_dru_gore : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GoreProc, SpellIds.Mangle); } - [Script] // 740 - Tranquility - class spell_dru_inner_peace : SpellScript + bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + return RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Unit owner = GetTarget(); + owner.CastSpell(owner, SpellIds.GoreProc); + owner.GetSpellHistory().ResetCooldown(SpellIds.Mangle, true); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 99 - Incapacitating Roar +class spell_dru_incapacitating_roar : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BearForm); + } + + void HandleOnCast() + { + // Change into cat form + if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.BearForm) + GetCaster().CastSpell(GetCaster(), SpellIds.BearForm, true); + } + + public override void Register() + { + BeforeCast.Add(new(HandleOnCast)); + } +} + +[Script] // 29166 - Innervate +class spell_dru_innervate : SpellScript +{ + SpellCastResult CheckCast() + { + Player target = GetExplTargetUnit()?.ToPlayer(); + if (target == null) + return SpellCastResult.BadTargets; + + ChrSpecializationRecord spec = target.GetPrimarySpecializationEntry(); + if (spec == null || spec.GetRole() != ChrSpecializationRole.Healer) + return SpellCastResult.BadTargets; + + return SpellCastResult.SpellCastOk; + } + + void HandleRank2() + { + Unit caster = GetCaster(); + if (caster != GetHitUnit()) { - return ValidateSpellInfo(SpellIds.InnerPeace) + AuraEffect innervateR2 = caster.GetAuraEffect(SpellIds.InnervateRank2, 0); + if (innervateR2 != null) + caster.CastSpell(caster, SpellIds.Innervate, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnoreCastInProgress) + .SetTriggeringSpell(GetSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, -innervateR2.GetAmount())); + } + + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnHit.Add(new(HandleRank2)); + } +} + +[Script] // 117679 - Incarnation (Passive) +class spell_dru_incarnation : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IncarnationTreeOfLife); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.IncarnationTreeOfLife); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.IgnoreSpellCooldown, AuraEffectHandleModes.Real)); + } +} + +[Script] // 33891 - Incarnation: Tree of Life (Talent, Shapeshift) +class spell_dru_incarnation_tree_of_life : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Incarnation); + } + + void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (!GetTarget().HasAura(SpellIds.Incarnation)) + GetTarget().CastSpell(GetTarget(), SpellIds.Incarnation, true); + } + + public override void Register() + { + AfterEffectApply.Add(new(AfterApply, 2, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 740 - Tranquility +class spell_dru_inner_peace : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.InnerPeace) && ValidateSpellEffect((spellInfo.Id, 4)) + && spellInfo.GetEffect(3).IsAura(AuraType.MechanicImmunityMask) && spellInfo.GetEffect(4).IsAura(AuraType.ModDamagePercentTaken); - } - - void PreventEffect(ref WorldObject target) - { - // Note: Inner Peace talent. - if (!GetCaster().HasAura(SpellIds.InnerPeace)) - target = null; - } - - public override void Register() - { - OnObjectTargetSelect.Add(new(PreventEffect, 3, Targets.UnitCaster)); - OnObjectTargetSelect.Add(new(PreventEffect, 4, Targets.UnitCaster)); - } } - [Script] // 40442 - Druid Tier 6 Trinket - class spell_dru_item_t6_trinket : AuraScript + void PreventEffect(ref WorldObject target) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlessingOfRemulos, SpellIds.BlessingOfElune, SpellIds.BlessingOfCenarius); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null) - return; - - uint spellId; - int chance; - - // Starfire - if (spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x00000004u)) - { - spellId = SpellIds.BlessingOfRemulos; - chance = 25; - } - // Rejuvenation - else if (spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x00000010u)) - { - spellId = SpellIds.BlessingOfElune; - chance = 25; - } - // Mangle (Bear) and Mangle (Cat) - else if (spellInfo.SpellFamilyFlags[1].HasAnyFlag(0x00000440u)) - { - spellId = SpellIds.BlessingOfCenarius; - chance = 40; - } - else - return; - - if (RandomHelper.randChance(chance)) - eventInfo.GetActor().CastSpell(null, spellId, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + // Note: Inner Peace talent. + if (!GetCaster().HasAura(SpellIds.InnerPeace)) + target = null; } - [Script] // 33763 - Lifebloom - class spell_dru_lifebloom : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellIds.LifebloomFinalHeal); - } + OnObjectTargetSelect.Add(new(PreventEffect, 3, Targets.UnitCaster)); + OnObjectTargetSelect.Add(new(PreventEffect, 4, Targets.UnitCaster)); + } +} - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // Final heal only on duration end - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire || GetTargetApplication().GetRemoveMode() == AuraRemoveMode.EnemySpell) - GetCaster().CastSpell(GetUnitOwner(), SpellIds.LifebloomFinalHeal, true); - } - - public override void Register() - { - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.Real)); - } +[Script] // 40442 - Druid Tier 6 Trinket +class spell_dru_item_t6_trinket : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlessingOfRemulos, SpellIds.BlessingOfElune, SpellIds.BlessingOfCenarius); } - [Script] // 155580 - Lunar Inspiration - class spell_dru_lunar_inspiration : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spell) + PreventDefaultAction(); + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null) + return; + + uint spellId; + int chance; + + // Starfire + if ((spellInfo.SpellFamilyFlags[0] & 0x00000004) != 0) { - return ValidateSpellInfo(SpellIds.LunarInspirationOverride); + spellId = SpellIds.BlessingOfRemulos; + chance = 25; } - - void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) + // Rejuvenation + else if ((spellInfo.SpellFamilyFlags[0] & 0x00000010) != 0) { - GetTarget().CastSpell(GetTarget(), SpellIds.LunarInspirationOverride, true); + spellId = SpellIds.BlessingOfElune; + chance = 25; } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + // Mangle (Bear) and Mangle (Cat) + else if ((spellInfo.SpellFamilyFlags[1] & 0x00000440) != 0) { - GetTarget().RemoveAurasDueToSpell(SpellIds.LunarInspirationOverride); + spellId = SpellIds.BlessingOfCenarius; + chance = 40; } + else + return; - public override void Register() - { - AfterEffectApply.Add(new(AfterApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 392315 - Luxuriant Soil - class spell_dru_luxuriant_soil : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Rejuvenation); - } - - static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(aurEff.GetAmount()); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit rejuvCaster = GetTarget(); - - // let's use the ProcSpell's max. range. - float spellRange = eventInfo.GetSpellInfo().GetMaxRange(); - - List targetList = new(); - WorldObjectSpellAreaTargetCheck check = new(spellRange, rejuvCaster, rejuvCaster, rejuvCaster, eventInfo.GetSpellInfo(), SpellTargetCheckTypes.Ally, null, SpellTargetObjectTypes.Unit); - UnitListSearcher searcher = new(rejuvCaster, targetList, check); - Cell.VisitAllObjects(rejuvCaster, searcher, spellRange); - - if (targetList.Empty()) - return; - - rejuvCaster.CastSpell(targetList.SelectRandom(), SpellIds.Rejuvenation, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 8921 - Moonfire - class spell_dru_moonfire : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MoonfireDamage); - } - - void HandleOnHit(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.MoonfireDamage, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.Dummy)); - } - } - - // 274283 - Full Moon - // 274282 - Half Moon - // 274281 - New Moon - [Script("spell_dru_full_moon", 0, SpellIds.HalfMoonOverride)] - [Script("spell_dru_half_moon", SpellIds.HalfMoonOverride, SpellIds.NewMoonOverride)] - [Script("spell_dru_new_moon", SpellIds.NewMoonOverride, 0)] - class spell_dru_new_moon : SpellScript - { - public spell_dru_new_moon(uint newOverrideSpell, uint removeOverrideSpell) - { - _newOverrideSpell = newOverrideSpell; - _removeOverrideSpell = removeOverrideSpell; - } - - public override bool Validate(SpellInfo spellInfo) - { - return (_newOverrideSpell == 0 || ValidateSpellInfo(_newOverrideSpell)) - && (_removeOverrideSpell == 0 || ValidateSpellInfo(_removeOverrideSpell)); - } - - void OverrideMoon() - { - Unit caster = GetCaster(); - if (_newOverrideSpell != 0) - caster.CastSpell(caster, _newOverrideSpell, new CastSpellExtraArgs() - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(GetSpell())); - - if (_removeOverrideSpell != 0) - caster.RemoveAurasDueToSpell(_removeOverrideSpell); - } - - public override void Register() - { - AfterCast.Add(new(OverrideMoon)); - } - - uint _newOverrideSpell; - uint _removeOverrideSpell; - } - - [Script] // 113043 - Omen of Clarity - class spell_dru_omen_of_clarity_restoration : AuraScript - { - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(aurEff.GetAmount()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } + if (RandomHelper.randChance(chance)) + eventInfo.GetActor().CastSpell(null, spellId, aurEff); } - [Script] // 16864 - Omen of Clarity - class spell_dru_omen_of_clarity : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BalanceT10Bonus, SpellIds.BalanceT10BonusProc); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit target = GetTarget(); - if (target.HasAura(SpellIds.BalanceT10Bonus)) - target.CastSpell(null, SpellIds.BalanceT10BonusProc, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } +[Script] // 33763 - Lifebloom +class spell_dru_lifebloom : AuraScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.LifebloomFinalHeal); } - [Script] // 392303 - Power of the Archdruid - class spell_dru_power_of_the_archdruid : AuraScript + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.PowerOfTheArchdruid, 0)); - } - - static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetActor().HasAuraEffect(SpellIds.PowerOfTheArchdruid, 0); - } - - static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit druid = eventInfo.GetActor(); - Unit procTarget = eventInfo.GetActionTarget(); - - // range is 0's BasePoints. - float spellRange = aurEff.GetAmount(); - - List targetList = new(); - WorldObjectSpellAreaTargetCheck checker = new(spellRange, procTarget, druid, druid, eventInfo.GetSpellInfo(), SpellTargetCheckTypes.Ally, null, SpellTargetObjectTypes.Unit); - UnitListSearcher searcher = new(procTarget, targetList, checker); - Cell.VisitAllObjects(procTarget, searcher, spellRange); - targetList.Remove(procTarget); - - if (targetList.Empty()) - return; - - AuraEffect powerOfTheArchdruidEffect = druid.GetAuraEffect(SpellIds.PowerOfTheArchdruid, 0); - - // max. targets is SpellPowerOfTheArchdruid's 0 BasePoints. - int maxTargets = powerOfTheArchdruidEffect.GetAmount(); - - targetList.RandomResize((uint)maxTargets); - - foreach (Unit chosenTarget in targetList) - druid.CastSpell(chosenTarget, eventInfo.GetProcSpell().GetSpellInfo().Id, aurEff); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + // Final heal only on duration end + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire || GetTargetApplication().GetRemoveMode() == AuraRemoveMode.EnemySpell) + GetCaster().CastSpell(GetUnitOwner(), SpellIds.LifebloomFinalHeal, true); } - [Script] // 5215 - Prowl - class spell_dru_prowl : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CatForm); - } - - void HandleOnCast() - { - if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.CatForm) - GetCaster().CastSpell(GetCaster(), SpellIds.CatForm, true); - } - - public override void Register() - { - BeforeCast.Add(new(HandleOnCast)); - } + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.Real)); } +} - [Script] // 1079 - Rip - class spell_dru_rip : AuraScript +[Script] // 204066 - Lunar Beam +class at_dru_lunar_beam(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TaskScheduler _scheduler = new(); + + public override void OnCreate(Spell creatingSpell) { - public override bool Load() + _scheduler.Schedule(TimeSpan.FromSeconds(500), task => { - Unit caster = GetCaster(); - return caster != null && caster.IsPlayer(); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - canBeRecalculated = false; - - Unit caster = GetCaster(); + Unit caster = at.GetCaster(); if (caster != null) { - // 0.01 * $Ap * cp - int cp = caster.GetPower(PowerType.ComboPoints); - - // Idol of Feral Shadows. Can't be handled as SpellMod due its dependency from CPs - AuraEffect auraEffIdolOfFeralShadows = caster.GetAuraEffect(SpellIds.IdolOfFeralShadows, 0); - if (auraEffIdolOfFeralShadows != null) - amount += cp * auraEffIdolOfFeralShadows.GetAmount(); - // Idol of Worship. Can't be handled as SpellMod due its dependency from CPs - else - { - AuraEffect auraEffIdolOfWorship = caster.GetAuraEffect(SpellIds.IdolOfWorship, 0); - if (auraEffIdolOfWorship != null) - amount += cp * auraEffIdolOfWorship.GetAmount(); - } - - amount += (int)MathFunctions.CalculatePct(caster.GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), cp); + caster.CastSpell(caster, SpellIds.LunarBeamHeal, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + caster.CastSpell(at.GetPosition(), SpellIds.LunarBeamDamage, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); } - } + task.Repeat(TimeSpan.FromSeconds(1)); - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.PeriodicDamage)); - } + }); } - [Script] // 52610 - Savage Roar - class spell_dru_savage_roar : SpellScript + public override void OnUpdate(uint diff) { - SpellCastResult CheckCast() - { - Unit caster = GetCaster(); - if (caster.GetShapeshiftForm() != ShapeShiftForm.CatForm) - return SpellCastResult.OnlyShapeshift; + _scheduler.Update(diff); + } +} - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - } +[Script] // 155580 - Lunar Inspiration +class spell_dru_lunar_inspiration : AuraScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.LunarInspirationOverride); } - [Script] - class spell_dru_savage_roar_AuraScript : AuraScript + void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellIds.SavageRoar); - } - - void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.CastSpell(target, SpellIds.SavageRoar, new CastSpellExtraArgs(aurEff) - .SetOriginalCaster(GetCasterGUID())); - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.SavageRoar); - } - - public override void Register() - { - AfterEffectApply.Add(new(AfterApply, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(AfterRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + GetTarget().CastSpell(GetTarget(), SpellIds.LunarInspirationOverride, true); } - // 164815 - Sunfire - [Script] // 164812 - Moonfire - class spell_dru_shooting_stars : AuraScript + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ShootingStars, SpellIds.ShootingStarsDamage); - } - - void OnTick(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster != null) - { - AuraEffect shootingStars = caster.GetAuraEffect(SpellIds.ShootingStars, 0); - if (shootingStars != null) - if (RandomHelper.randChance(shootingStars.GetAmount())) - caster.CastSpell(GetTarget(), SpellIds.ShootingStarsDamage, true); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(OnTick, 1, AuraType.PeriodicDamage)); - } + GetTarget().RemoveAurasDueToSpell(SpellIds.LunarInspirationOverride); } - [Script] // 106839 - Skull Bash - class spell_dru_skull_bash : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SkullBashCharge, SpellIds.SkullBashInterrupt); - } + AfterEffectApply.Add(new(AfterApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.SkullBashCharge, true); - GetCaster().CastSpell(GetHitUnit(), SpellIds.SkullBashInterrupt, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } +[Script] // 392315 - Luxuriant Soil +class spell_dru_luxuriant_soil : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Rejuvenation); } - [Script] // 81269 - Efflorescence (Heal) - class spell_dru_spring_blossoms : SpellScript + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SpringBlossoms, SpellIds.SpringBlossomsHeal); - } - - void HandleOnHit(uint effIndex) - { - if (GetCaster().HasAura(SpellIds.SpringBlossoms)) - GetCaster().CastSpell(GetHitUnit(), SpellIds.SpringBlossomsHeal, TriggerCastFlags.DontReportCastError); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.Heal)); - } + return RandomHelper.randChance(aurEff.GetAmount()); } - [Script] // 106898 - Stampeding Roar - class spell_dru_stampeding_roar : SpellScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BearForm); - } + Unit rejuvCaster = GetTarget(); - void HandleOnCast() - { - if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.BearForm) - GetCaster().CastSpell(GetCaster(), SpellIds.BearForm, true); - } + // let's use the ProcSpell's max. range. + float spellRange = eventInfo.GetSpellInfo().GetMaxRange(); - public override void Register() - { - BeforeCast.Add(new(HandleOnCast)); - } + List targetList = new(); + WorldObjectSpellAreaTargetCheck check = new(spellRange, rejuvCaster, rejuvCaster, rejuvCaster, eventInfo.GetSpellInfo(), SpellTargetCheckTypes.Ally, null, SpellTargetObjectTypes.Unit); + UnitListSearcher searcher = new(rejuvCaster, targetList, check); + Cell.VisitAllObjects(rejuvCaster, searcher, spellRange); + + if (targetList.Empty()) + return; + + rejuvCaster.CastSpell(targetList.SelectRandom(), SpellIds.Rejuvenation, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress); } - [Script] // 50286 - Starfall (Dummy) - class spell_dru_starfall_dummy : SpellScript + public override void Register() { - void FilterTargets(List targets) - { - targets.RandomResize(2); - } + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - // Shapeshifting into an animal form or mounting cancels the effect - if (caster.GetCreatureType() == CreatureType.Beast || caster.IsMounted()) - { - SpellInfo spellInfo = GetTriggeringSpell(); - if (spellInfo != null) - caster.RemoveAurasDueToSpell(spellInfo.Id); - return; - } - - // Any effect which causes you to lose control of your character will supress the starfall effect. - if (caster.HasUnitState(UnitState.Controlled)) - return; - - caster.CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } +[Script] // 33917 - Mangle +class spell_dru_mangle : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MangleTalent) + && ValidateSpellEffect((spellInfo.Id, 2)); } - [Script] // 202347 - Stellar Flare - class spell_dru_stellar_flare : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.StarBurst); - } - - void HandleDispel(DispelInfo dispelInfo) - { - GetCaster()?.CastSpell(dispelInfo.GetDispeller(), SpellIds.StarBurst, true); - } - - public override void Register() - { - AfterDispel.Add(new(HandleDispel)); - } + return GetCaster().HasAura(SpellIds.MangleTalent); } - // 340694 - Sudden Ambush - [Script] // 384667 - Sudden Ambush - class spell_dru_sudden_ambush : AuraScript + + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) { - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Spell procSpell = procInfo.GetProcSpell(); - if (procSpell == null) - return false; - - int? comboPoints = procSpell.GetPowerTypeCostAmount(PowerType.ComboPoints); - if (!comboPoints.HasValue) - return false; - - return RandomHelper.randChance(comboPoints.Value * aurEff.GetAmount()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } + if (victim.HasAuraState(AuraStateType.Bleed)) + MathFunctions.AddPct(ref pctMod, GetEffectInfo(2).CalcValue(GetCaster())); } - [Script] // 93402 - Sunfire - class spell_dru_sunfire : SpellScript + public override void Register() { - void HandleOnHit(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.SunfireDamage, true); - } + CalcDamage.Add(new(CalculateDamage)); + } +} - public override void Register() - { - OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.Dummy)); - } +[Script] // 8921 - Moonfire +class spell_dru_moonfire : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MoonfireDamage); } - [Script] // 61336 - Survival Instincts - class spell_dru_survival_instincts : AuraScript + void HandleOnHit(uint effIndex) { - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellIds.SurvivalInstincts); - } - - void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().CastSpell(GetTarget(), SpellIds.SurvivalInstincts, true); - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.SurvivalInstincts); - } - - public override void Register() - { - AfterEffectApply.Add(new(AfterApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + GetCaster().CastSpell(GetHitUnit(), SpellIds.MoonfireDamage, true); } - [Script] // 40121 - Swift Flight Form (Passive) - class spell_dru_swift_flight_passive : AuraScript + public override void Register() { - public override bool Load() - { - return GetCaster().IsPlayer(); - } + OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.Dummy)); + } +} - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player caster = GetCaster().ToPlayer(); - if (caster != null) - if (caster.GetSkillValue(SkillType.Riding) >= 375) - amount = 310; - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ModIncreaseVehicleFlightSpeed)); - } +[Script] // 450347 - Nature's Grace +class spell_dru_natures_grace : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NaturesGraceTalent, SpellIds.Dreamstate) + && ValidateSpellEffect((spellInfo.Id, 2)); } - [Script] // 28744 - Regrowth - class spell_dru_t3_6p_bonus : AuraScript + public static void Trigger(Unit caster, AuraEffect naturesGraceEffect) { - public override bool Validate(SpellInfo spellInfo) + caster.CastSpell(caster, SpellIds.Dreamstate, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.BlessingOfTheClaw); - } + SpellValueOverrides = { new(SpellValueMod.AuraStack, naturesGraceEffect.GetAmount()) } + }); - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.BlessingOfTheClaw, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.OverrideClassScripts)); - } } - [Script] // 28719 - Healing Touch - class spell_dru_t3_8p_bonus : AuraScript + void OnOwnerInCombat(bool isNowInCombat) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Exhilarate); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Spell spell = eventInfo.GetProcSpell(); - if (spell == null) - return; - - Unit caster = eventInfo.GetActor(); - int? manaCost = spell.GetPowerTypeCostAmount(PowerType.Mana); - if (!manaCost.HasValue) - return; - - int amount = MathFunctions.CalculatePct(manaCost.Value, aurEff.GetAmount()); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(null, SpellIds.Exhilarate, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + if (isNowInCombat) + Trigger(GetTarget(), GetEffect(2)); } - // 37288 - Mana Restore - [Script] // 37295 - Mana Restore - class spell_dru_t4_2p_bonus : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Infusion); - } + OnEnterLeaveCombat.Add(new(OnOwnerInCombat)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - eventInfo.GetActor().CastSpell(null, SpellIds.Infusion, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 48517 Eclipse (Solar) + 48518 Eclipse (Lunar) +class spell_dru_natures_grace_eclipse : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Dreamstate) + && ValidateSpellEffect((SpellIds.NaturesGraceTalent, 2)); } - [Script] // 70723 - Item - Druid T10 Balance 4P Bonus - class spell_dru_t10_balance_4p_bonus : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Languish); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; - - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.Languish, GetCastDifficulty()); - int amount = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount()); - - Cypher.Assert(spellInfo.GetMaxTicks() > 0); - amount /= (int)spellInfo.GetMaxTicks(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(target, SpellIds.Languish, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + return GetCaster().HasAuraEffect(SpellIds.NaturesGraceTalent, 2); } - [Script] // 70691 - Item T10 Restoration 4P Bonus - class spell_dru_t10_restoration_4p_bonus : SpellScript - { - public override bool Load() - { - return GetCaster().IsPlayer(); - } - void FilterTargets(List targets) + void HandleRemoved(AuraEffect aurEff, AuraEffectHandleModes mode) + { + spell_dru_natures_grace.Trigger(GetTarget(), GetTarget().GetAuraEffect(SpellIds.NaturesGraceTalent, 2)); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleRemoved, 0, AuraType.AddPctModifier, AuraEffectHandleModes.Real)); + } +} + +[Script("spell_dru_full_moon", 0, SpellIds.HalfMoonOverride)] // 274283 - Full Moon +[Script("spell_dru_half_moon", SpellIds.HalfMoonOverride, SpellIds.NewMoonOverride)] // 274282 - Half Moon +[Script("spell_dru_new_moon", SpellIds.NewMoonOverride, 0)] // 274281 - New Moon +class spell_dru_new_moon(uint newOverrideSpell, uint removeOverrideSpell) : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return (newOverrideSpell == 0 || ValidateSpellInfo(newOverrideSpell)) + && (removeOverrideSpell == 0 || ValidateSpellInfo(removeOverrideSpell)); + } + + void OverrideMoon() + { + Unit caster = GetCaster(); + if (newOverrideSpell != 0) + caster.CastSpell(caster, newOverrideSpell, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); + + if (removeOverrideSpell != 0) + caster.RemoveAurasDueToSpell(removeOverrideSpell); + } + + public override void Register() + { + AfterCast.Add(new(OverrideMoon)); + } +} + +[Script] // 16864 - Omen of Clarity +class spell_dru_omen_of_clarity : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BalanceT10_Bonus, SpellIds.BalanceT10_BonusProc); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + if (target.HasAura(SpellIds.BalanceT10_Bonus)) + target.CastSpell(null, SpellIds.BalanceT10_BonusProc, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 113043 - Omen of Clarity +class spell_dru_omen_of_clarity_restoration : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 392303 - Power of the Archdruid +class spell_dru_power_of_the_archdruid : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.PowerOfTheArchdruid, 0)); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActor().HasAuraEffect(SpellIds.PowerOfTheArchdruid, 0); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit druid = eventInfo.GetActor(); + Unit procTarget = eventInfo.GetActionTarget(); + + // range is 0's BasePoints. + float spellRange = aurEff.GetAmount(); + + List targetList = new(); + WorldObjectSpellAreaTargetCheck checker = new(spellRange, procTarget, druid, druid, eventInfo.GetSpellInfo(), SpellTargetCheckTypes.Ally, null, SpellTargetObjectTypes.Unit); + UnitListSearcher searcher = new(procTarget, targetList, checker); + Cell.VisitAllObjects(procTarget, searcher, spellRange); + targetList.Remove(procTarget); + + if (targetList.Empty()) + return; + + AuraEffect powerOfTheArchdruidEffect = druid.GetAuraEffect(SpellIds.PowerOfTheArchdruid, 0); + + // max. targets is SpellIds.PowerOfTheArchdruid's 0 BasePoints. + int maxTargets = powerOfTheArchdruidEffect.GetAmount(); + + targetList.RandomResize((uint)maxTargets); + + foreach (Unit chosenTarget in targetList) + druid.CastSpell(chosenTarget, eventInfo.GetProcSpell().GetSpellInfo().Id, aurEff); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 5215 - Prowl +class spell_dru_prowl : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CatForm); + } + + void HandleOnCast() + { + // Change into cat form + if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.CatForm) + GetCaster().CastSpell(GetCaster(), SpellIds.CatForm, true); + } + + public override void Register() + { + BeforeCast.Add(new(HandleOnCast)); + } +} + +[Script] // 1079 - Rip +class spell_dru_rip : AuraScript +{ + public override bool Load() + { + Unit caster = GetCaster(); + return caster != null && caster.IsPlayer(); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = false; + + Unit caster = GetCaster(); + if (caster != null) { - if (GetCaster().ToPlayer().GetGroup() == null) - { - targets.Clear(); - targets.Add(GetCaster()); - } + // 0.01 * $Ap * cp + int cp = caster.GetPower(PowerType.ComboPoints); + + // Idol of Feral Shadows. Can't be handled as SpellMod due its dependency from CPs + AuraEffect auraEffIdolOfFeralShadows = caster.GetAuraEffect(SpellIds.IdolOfFeralShadows, 0); + if (auraEffIdolOfFeralShadows != null) + amount += cp * auraEffIdolOfFeralShadows.GetAmount(); + // Idol of Worship. Can't be handled as SpellMod due its dependency from CPs else { - targets.Remove(GetExplTargetUnit()); - List tempTargets = new(); - foreach (var obj in targets) - if (obj.IsPlayer() && GetCaster().IsInRaidWith(obj.ToUnit())) - tempTargets.Add(obj.ToUnit()); - - if (tempTargets.Empty()) - { - targets.Clear(); - FinishCast(SpellCastResult.DontReport); - return; - } - - Unit target = tempTargets.SelectRandom(); - targets.Clear(); - targets.Add(target); + AuraEffect auraEffIdolOfWorship = caster.GetAuraEffect(SpellIds.IdolOfWorship, 0); + if (auraEffIdolOfWorship != null) + amount += cp * auraEffIdolOfWorship.GetAmount(); } - } - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + amount += (int)MathFunctions.CalculatePct(caster.GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), cp); } } - [Script] // 70664 - Druid T10 Restoration 4P Bonus (Rejuvenation) - class spell_dru_t10_restoration_4p_bonus_dummy : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.PeriodicDamage)); + } +} + +[Script] // 52610 - Savage Roar +class spell_dru_savage_roar : SpellScript +{ + SpellCastResult CheckCast() + { + Unit caster = GetCaster(); + if (caster.GetShapeshiftForm() != ShapeShiftForm.CatForm) + return SpellCastResult.OnlyShapeshift; + + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + } +} + +[Script] +class spell_dru_savage_roar_aura : AuraScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.SavageRoar); + } + + void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.SavageRoar, new CastSpellExtraArgs(aurEff) + .SetOriginalCaster(GetCasterGUID())); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.SavageRoar); + } + + public override void Register() + { + AfterEffectApply.Add(new(AfterApply, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 202342 - Shooting Stars +class spell_dru_shooting_stars : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShootingStarsDamage) + && ValidateSpellEffect((SpellIds.MoonfireDamage, 1), (SpellIds.SunfireDamage, 1)) + && Global.SpellMgr.GetSpellInfo(SpellIds.MoonfireDamage, Difficulty.None).GetEffect(1).IsAura(AuraType.PeriodicDamage) + && Global.SpellMgr.GetSpellInfo(SpellIds.SunfireDamage, Difficulty.None).GetEffect(1).IsAura(AuraType.PeriodicDamage); + } + + void OnTick(AuraEffect aurEff) + { + Unit caster = GetTarget(); + List moonfires = new(); + List sunfires = new(); + var druid = caster.GetGUID(); + void work(Unit target) { - return ValidateSpellInfo(SpellIds.RejuvenationT10Proc); + if (target.HasAuraEffect(SpellIds.MoonfireDamage, 1, druid)) + moonfires.Add(target); + + if (target.HasAuraEffect(SpellIds.SunfireDamage, 1, druid)) + sunfires.Add(target); } + ; + UnitWorker worker = new(caster, work); + Cell.VisitAllObjects(caster, worker, 100.0f); - bool CheckProc(ProcEventInfo eventInfo) + ProcessDoT(aurEff, caster, moonfires); + ProcessDoT(aurEff, caster, sunfires); + } + + static void ProcessDoT(AuraEffect aurEff, Unit caster, List targets) + { + if (targets.Empty()) + return; + + float chance = (float)(aurEff.GetAmount() * MathF.Sqrt(targets.Count)); + float procs = MathF.Truncate(chance / 100.0f); + if (RandomHelper.randChance(procs * 100.0f)) + procs += 1.0f; + + if (procs <= 0.0f) + return; + + targets.RandomResize((uint)procs); + foreach (Unit target in targets) { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null || spellInfo.Id == SpellIds.RejuvenationT10Proc) - return false; - - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo == null || healInfo.GetHeal() == 0) - return false; - - Player caster = eventInfo.GetActor().ToPlayer(); - if (caster == null) - return false; - - return caster.GetGroup() != null || caster != eventInfo.GetProcTarget(); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)eventInfo.GetHealInfo().GetHeal()); - eventInfo.GetActor().CastSpell(null, SpellIds.RejuvenationT10Proc, args); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + caster.CastSpell(target, SpellIds.ShootingStarsDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); } } - [Script] // 77758 - Thrash - class spell_dru_thrash : SpellScript + + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnEffectPeriodic.Add(new(OnTick, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 106839 - Skull Bash +class spell_dru_skull_bash : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SkullBashCharge, SpellIds.SkullBashInterrupt); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.SkullBashCharge, true); + GetCaster().CastSpell(GetHitUnit(), SpellIds.SkullBashInterrupt, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 81269 - Efflorescence (Heal) +class spell_dru_spring_blossoms : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SpringBlossoms, SpellIds.SpringBlossomsHeal); + } + + void HandleOnHit(uint effIndex) + { + if (GetCaster().HasAura(SpellIds.SpringBlossoms)) + GetCaster().CastSpell(GetHitUnit(), SpellIds.SpringBlossomsHeal, TriggerCastFlags.DontReportCastError); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.Heal)); + } +} + +[Script] // 106898 - Stampeding Roar +class spell_dru_stampeding_roar : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BearForm); + } + + void HandleOnCast() + { + // Change into cat form + if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.BearForm) + GetCaster().CastSpell(GetCaster(), SpellIds.BearForm, true); + } + + public override void Register() + { + BeforeCast.Add(new(HandleOnCast)); + } +} + +[Script] // 50286 - Starfall (Dummy) +class spell_dru_starfall_dummy : SpellScript +{ + void FilterTargets(List targets) + { + targets.RandomResize(2); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + // Shapeshifting into an animal form or mounting cancels the effect + if (caster.GetCreatureType() == CreatureType.Beast || caster.IsMounted()) { - return ValidateSpellInfo(SpellIds.ThrashBearAura); + SpellInfo spellInfo = GetTriggeringSpell(); + if (spellInfo != null) + caster.RemoveAurasDueToSpell(spellInfo.Id); + return; } - void HandleOnHitTarget(uint effIndex) - { - Unit hitUnit = GetHitUnit(); - if (hitUnit != null) - GetCaster().CastSpell(hitUnit, SpellIds.ThrashBearAura, TriggerCastFlags.FullMask); - } + // Any effect which causes you to lose control of your character will supress the starfall effect. + if (caster.HasUnitState(UnitState.Controlled)) + return; - public override void Register() + caster.CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 202347 - Stellar Flare +class spell_dru_stellar_flare : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StarBurst); + } + + void HandleDispel(DispelInfo dispelInfo) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(dispelInfo.GetDispeller(), SpellIds.StarBurst, true); + } + + public override void Register() + { + AfterDispel.Add(new(HandleDispel)); + } +} + +// 340694 - Sudden Ambush +[Script] // 384667 - Sudden Ambush +class spell_dru_sudden_ambush : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Spell procSpell = procInfo.GetProcSpell(); + if (procSpell == null) + return false; + + var comboPoints = procSpell.GetPowerTypeCostAmount(PowerType.ComboPoints); + if (!comboPoints.HasValue) + return false; + + return RandomHelper.randChance(comboPoints.Value * aurEff.GetAmount()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 93402 - Sunfire +class spell_dru_sunfire : SpellScript +{ + void HandleOnHit(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.SunfireDamage, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 61336 - Survival Instincts +class spell_dru_survival_instincts : AuraScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.SurvivalInstincts); + } + + void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().CastSpell(GetTarget(), SpellIds.SurvivalInstincts, true); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.SurvivalInstincts); + } + + public override void Register() + { + AfterEffectApply.Add(new(AfterApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 40121 - Swift Flight Form (Passive) +class spell_dru_swift_flight_passive : AuraScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player caster = GetCaster().ToPlayer(); + if (caster != null && caster.GetSkillValue(SkillType.Riding) >= 375) + amount = 310; + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ModIncreaseVehicleFlightSpeed)); + } +} + +[Script] // 28744 - Regrowth +class spell_dru_t3_6p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlessingOfTheClaw); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.BlessingOfTheClaw, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.OverrideClassScripts)); + } +} + +[Script] // 28719 - Healing Touch +class spell_dru_t3_8p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Exhilarate); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Spell spell = eventInfo.GetProcSpell(); + if (spell == null) + return; + + Unit caster = eventInfo.GetActor(); + var manaCost = spell.GetPowerTypeCostAmount(PowerType.Mana); + if (!manaCost.HasValue) + return; + + int amount = MathFunctions.CalculatePct(manaCost.Value, aurEff.GetAmount()); + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, amount); + caster.CastSpell(null, SpellIds.Exhilarate, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// 37288 - Mana Restore +[Script] // 37295 - Mana Restore +class spell_dru_t4_2p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Infusion); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + eventInfo.GetActor().CastSpell(null, SpellIds.Infusion, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 70723 - Item - Druid T10 Balance 4P Bonus +class spell_dru_t10_balance_4p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Languish); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.Languish, GetCastDifficulty()); + int amount = MathFunctions.CalculatePct((int)(damageInfo.GetDamage()), aurEff.GetAmount()); + + Cypher.Assert(spellInfo.GetMaxTicks() > 0); + amount /= (int)spellInfo.GetMaxTicks(); + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, amount); + caster.CastSpell(target, SpellIds.Languish, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 70691 - Item T10 Restoration 4P Bonus +class spell_dru_t10_restoration_4p_bonus : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void FilterTargets(List targets) + { + if (GetCaster().ToPlayer().GetGroup() == null) { - OnEffectHitTarget.Add(new(HandleOnHitTarget, 0, SpellEffectName.SchoolDamage)); + targets.Clear(); + targets.Add(GetCaster()); + } + else + { + targets.Remove(GetExplTargetUnit()); + List tempTargets = new(); + foreach (var obj in targets) + if (obj.IsPlayer() && GetCaster().IsInRaidWith(obj.ToUnit())) + tempTargets.Add(obj.ToUnit()); + + if (tempTargets.Empty()) + { + targets.Clear(); + FinishCast(SpellCastResult.DontReport); + return; + } + + Unit target = tempTargets.SelectRandom(); + targets.Clear(); + targets.Add(target); } } - [Script] // 192090 - Thrash (Aura) - SpellThrashBearAura - class spell_dru_thrash_AuraScript : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BloodFrenzyAura, SpellIds.BloodFrenzyRageGain); - } + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} - void HandlePeriodic(AuraEffect aurEff) +[Script] // 70664 - Druid T10 Restoration 4P Bonus (Rejuvenation) +class spell_dru_t10_restoration_4p_bonus_dummy : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RejuvenationT10_Proc); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null || spellInfo.Id == SpellIds.RejuvenationT10_Proc) + return false; + + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo == null || healInfo.GetHeal() == 0) + return false; + + Player caster = eventInfo.GetActor().ToPlayer(); + if (caster == null) + return false; + + return caster.GetGroup() != null || caster != eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)eventInfo.GetHealInfo().GetHeal()); + eventInfo.GetActor().CastSpell(null, SpellIds.RejuvenationT10_Proc, args); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 77758 - Thrash +class spell_dru_thrash : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ThrashBearAura); + } + + void HandleOnHitTarget(uint effIndex) + { + Unit hitUnit = GetHitUnit(); + if (hitUnit != null) { Unit caster = GetCaster(); - if (caster != null) - if (caster.HasAura(SpellIds.BloodFrenzyAura)) - caster.CastSpell(caster, SpellIds.BloodFrenzyRageGain, true); - } - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDamage)); + caster.CastSpell(hitUnit, SpellIds.ThrashBearAura, TriggerCastFlags.FullMask); } } - // 1066 - Aquatic Form - // 33943 - Flight Form - // 40120 - Swift Flight Form - [Script] // 165961 - Stag Form - class spell_dru_travel_form : AuraScript + public override void Register() { - uint triggeredSpellId; + OnEffectHitTarget.Add(new(HandleOnHitTarget, 0, SpellEffectName.SchoolDamage)); + } +} - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FormStag, SpellIds.FormAquaticPassive, SpellIds.FormAquatic, SpellIds.FormFlight, SpellIds.FormSwiftFlight); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // If it stays 0, it Removes Travel Form dummy in AfterRemove. - triggeredSpellId = 0; - - // We should only handle aura interrupts. - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Interrupt) - return; - - // Check what form is appropriate - triggeredSpellId = GetFormSpellId(GetTarget().ToPlayer(), GetCastDifficulty(), true); - - // If chosen form is current aura, just don't Remove it. - if (triggeredSpellId == m_scriptSpellId) - PreventDefaultAction(); - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (triggeredSpellId == m_scriptSpellId) - return; - - Player player = GetTarget().ToPlayer(); - - if (triggeredSpellId != 0) // Apply new form - player.CastSpell(player, triggeredSpellId, aurEff); - else // If not set, simply Remove Travel Form dummy - player.RemoveAura(SpellIds.TravelForm); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); - } - - public static uint GetFormSpellId(Player player, Difficulty difficulty, bool requiresOutdoor) - { - // Check what form is appropriate - if (player.HasSpell(SpellIds.FormAquaticPassive) && player.IsInWater()) // Aquatic form - return SpellIds.FormAquatic; - - if (!player.IsInCombat() && player.GetSkillValue(SkillType.Riding) >= 225 && CheckLocationForForm(player, difficulty, requiresOutdoor, SpellIds.FormFlight) == SpellCastResult.SpellCastOk) // Flight form - return player.GetSkillValue(SkillType.Riding) >= 300 ? SpellIds.FormSwiftFlight : SpellIds.FormFlight; - - if (!player.IsInWater() && CheckLocationForForm(player, difficulty, requiresOutdoor, SpellIds.FormStag) == SpellCastResult.SpellCastOk) // Stag form - return SpellIds.FormStag; - - return 0; - } - - static SpellCastResult CheckLocationForForm(Player targetPlayer, Difficulty difficulty, bool requireOutdoors, uint spellId) - { - SpellInfo spellInfo = SpellMgr.GetSpellInfo(spellId, difficulty); - - if (requireOutdoors && !targetPlayer.IsOutdoors()) - return SpellCastResult.OnlyOutdoors; - - return spellInfo.CheckLocation(targetPlayer.GetMapId(), targetPlayer.GetZoneId(), targetPlayer.GetAreaId(), targetPlayer); - } +[Script] // 192090 - Thrash (Aura) - SpellIds.ThrashBearAura +class spell_dru_thrash_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BloodFrenzyAura, SpellIds.BloodFrenzyRageGain); } - [Script] // 783 - Travel Form (dummy) - class spell_dru_travel_form_dummy : SpellScript + void HandlePeriodic(AuraEffect aurEff) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FormAquaticPassive, SpellIds.FormAquatic, SpellIds.FormStag); - } - - SpellCastResult CheckCast() - { - Player player = GetCaster().ToPlayer(); - if (player == null) - return SpellCastResult.CustomError; - - uint spellId = (player.HasSpell(SpellIds.FormAquaticPassive) && player.IsInWater()) ? SpellIds.FormAquatic : SpellIds.FormStag; - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(spellId, GetCastDifficulty()); - return spellInfo.CheckLocation(player.GetMapId(), player.GetZoneId(), player.GetAreaId(), player); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - } + Unit caster = GetCaster(); + if (caster != null) + if (caster.HasAura(SpellIds.BloodFrenzyAura)) + caster.CastSpell(caster, SpellIds.BloodFrenzyRageGain, true); } - [Script] - class spell_dru_travel_form_dummy_AuraScript : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FormStag, SpellIds.FormAquatic, SpellIds.FormFlight, SpellIds.FormSwiftFlight); - } + OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDamage)); + } +} - public override bool Load() - { - return GetCaster().IsPlayer(); - } +// 1066 - Aquatic Form +// 33943 - Flight Form +// 40120 - Swift Flight Form +[Script] // 165961 - Stag Form +class spell_dru_travel_form : AuraScript +{ + uint triggeredSpellId = 0; - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Player player = GetTarget().ToPlayer(); + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FormStag, SpellIds.FormAquaticPassive, SpellIds.FormAquatic, SpellIds.FormFlight, SpellIds.FormSwiftFlight); + } - // Outdoor check already passed - Travel Form (dummy) has SpellAttr0OutdoorsOnly attribute. - uint triggeredSpellId = spell_dru_travel_form.GetFormSpellId(player, GetCastDifficulty(), false); + public override bool Load() + { + return GetCaster().IsPlayer(); + } + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // If it stays 0, it removes Travel Form dummy in AfterRemove. + triggeredSpellId = 0; + + // We should only handle aura interrupts. + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Interrupt) + return; + + // Check what form is appropriate + triggeredSpellId = GetFormSpellId(GetTarget().ToPlayer(), GetCastDifficulty(), true); + + // If chosen form is current aura, just don't remove it. + if (triggeredSpellId == m_scriptSpellId) + PreventDefaultAction(); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (triggeredSpellId == m_scriptSpellId) + return; + + Player player = GetTarget().ToPlayer(); + + if (triggeredSpellId != 0) // Apply new form player.CastSpell(player, triggeredSpellId, aurEff); - } + else // If not set, simply remove Travel Form dummy + player.RemoveAura(SpellIds.TravelForm); + } - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // No need to check Remove mode, it's safe for auras to Remove each other in AfterRemove hook. - GetTarget().RemoveAura(SpellIds.FormStag); - GetTarget().RemoveAura(SpellIds.FormAquatic); - GetTarget().RemoveAura(SpellIds.FormFlight); - GetTarget().RemoveAura(SpellIds.FormSwiftFlight); - } + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.ModShapeshift, AuraEffectHandleModes.Real)); + } - public override void Register() + public static uint GetFormSpellId(Player player, Difficulty difficulty, bool requiresOutdoor) + { + // Check what form is appropriate + if (player.HasSpell(SpellIds.FormAquaticPassive) && player.IsInWater()) // Aquatic form + return SpellIds.FormAquatic; + + if (!player.IsInCombat() && player.GetSkillValue(SkillType.Riding) >= 225 && CheckLocationForForm(player, difficulty, requiresOutdoor, SpellIds.FormFlight) == SpellCastResult.SpellCastOk) // Flight form + return player.GetSkillValue(SkillType.Riding) >= 300 ? SpellIds.FormSwiftFlight : SpellIds.FormFlight; + + if (!player.IsInWater() && CheckLocationForForm(player, difficulty, requiresOutdoor, SpellIds.FormStag) == SpellCastResult.SpellCastOk) // Stag form + return SpellIds.FormStag; + + return 0; + } + + static SpellCastResult CheckLocationForForm(Player targetPlayer, Difficulty difficulty, bool requireOutdoors, uint spell_id) + { + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spell_id, difficulty); + + if (requireOutdoors && !targetPlayer.IsOutdoors()) + return SpellCastResult.OnlyOutdoors; + + return spellInfo.CheckLocation(targetPlayer.GetMapId(), targetPlayer.GetZoneId(), targetPlayer.GetAreaId(), targetPlayer); + } +} + +[Script] // 783 - Travel Form (dummy) +class spell_dru_travel_form_dummy : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FormAquaticPassive, SpellIds.FormAquatic, SpellIds.FormStag); + } + + SpellCastResult CheckCast() + { + Player player = GetCaster().ToPlayer(); + if (player == null) + return SpellCastResult.CustomError; + + uint spellId = (player.HasSpell(SpellIds.FormAquaticPassive) && player.IsInWater()) ? SpellIds.FormAquatic : SpellIds.FormStag; + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, GetCastDifficulty()); + return spellInfo.CheckLocation(player.GetMapId(), player.GetZoneId(), player.GetAreaId(), player); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + } +} + +[Script] +class spell_dru_travel_form_dummy_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FormStag, SpellIds.FormAquatic, SpellIds.FormFlight, SpellIds.FormSwiftFlight); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Player player = GetTarget().ToPlayer(); + + // Outdoor check already passed - Travel Form (dummy) has SpellATTR0_OutdoorsOnly attribute. + uint triggeredSpellId = spell_dru_travel_form.GetFormSpellId(player, GetCastDifficulty(), false); + + player.CastSpell(player, triggeredSpellId, aurEff); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // No need to check remove mode, it's safe for auras to remove each other in AfterRemove hook. + GetTarget().RemoveAura(SpellIds.FormStag); + GetTarget().RemoveAura(SpellIds.FormAquatic); + GetTarget().RemoveAura(SpellIds.FormFlight); + GetTarget().RemoveAura(SpellIds.FormSwiftFlight); + } + + public override void Register() + { + OnEffectApply.Add(new(OnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 252216 - Tiger Dash +class spell_dru_tiger_dash : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CatForm); + } + + void HandleOnCast() + { + // Change into cat form + if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.CatForm) + GetCaster().CastSpell(GetCaster(), SpellIds.CatForm, true); + } + + public override void Register() + { + BeforeCast.Add(new(HandleOnCast)); + } +} + +[Script] // 252216 - Tiger Dash (Aura) +class spell_dru_tiger_dash_aura : AuraScript +{ + void HandlePeriodic(AuraEffect aurEff) + { + AuraEffect effRunSpeed = GetEffect(0); + if (effRunSpeed != null) { - OnEffectApply.Add(new(OnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + int reduction = aurEff.GetAmount(); + effRunSpeed.ChangeAmount(effRunSpeed.GetAmount() - reduction); } } - [Script] // 252216 - Tiger Dash - class spell_dru_tiger_dash : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CatForm); - } + OnEffectPeriodic.Add(new(HandlePeriodic, 1, AuraType.PeriodicDummy)); + } +} - void HandleOnCast() - { - if (GetCaster().GetShapeshiftForm() != ShapeShiftForm.CatForm) - GetCaster().CastSpell(GetCaster(), SpellIds.CatForm, true); - } - - public override void Register() - { - BeforeCast.Add(new(HandleOnCast)); - } +[Script] // 393763 - Umbral Embrace +class spell_dru_umbral_embrace : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EclipseLunarAura, SpellIds.EclipseSolarAura); } - [Script] // 252216 - Tiger Dash (Aura) - class spell_dru_tiger_dash_AuraScript : AuraScript + static bool CheckEclipse(ProcEventInfo eventInfo) { - void HandlePeriodic(AuraEffect aurEff) - { - AuraEffect effRunSpeed = GetEffect(0); - if (effRunSpeed != null) - { - int reduction = aurEff.GetAmount(); - effRunSpeed.ChangeAmount(effRunSpeed.GetAmount() - reduction); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodic, 1, AuraType.PeriodicDummy)); - } + return eventInfo.GetActor().HasAura(SpellIds.EclipseLunarAura) || eventInfo.GetActor().HasAura(SpellIds.EclipseSolarAura); } - [Script] // 48438 - Wild Growth - class spell_dru_wild_growth : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1), (SpellIds.TreeOfLife, 2)); - } + DoCheckProc.Add(new(CheckEclipse)); + } +} - void FilterTargets(List targets) - { - Unit caster = GetCaster(); - int maxTargets = GetEffectInfo(1).CalcValue(caster); - - AuraEffect treeOfLife = caster.GetAuraEffect(SpellIds.TreeOfLife, 2); - if (treeOfLife != null) - maxTargets += treeOfLife.GetAmount(); - - // Note: Wild Growth became a smart heal which prioritizes players and their pets in their group before any unit outside their group. - SelectRandomInjuredTargets(targets, (uint)maxTargets, true, caster); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - } +[Script] // 393763 - Umbral Embrace (attached to 190984 - Wrath and 194153 - Starfire) +class spell_dru_umbral_embrace_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EclipseLunarAura, SpellIds.EclipseSolarAura) + && ValidateSpellEffect((SpellIds.UmbralEmbrace, 0)); } - [Script] - class spell_dru_wild_growth_AuraScript : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RestorationT102PBonus); - } - - void HandleTickUpdate(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - // calculate from base damage, not from aurEff.GetAmount() (already modified) - float damage = caster.CalculateSpellDamage(GetUnitOwner(), aurEff.GetSpellEffectInfo()); - - // Wild Growth = first tick gains a 6% bonus, reduced by 2% each tick - float reduction = 2.0f; - AuraEffect bonus = caster.GetAuraEffect(SpellIds.RestorationT102PBonus, 0); - if (bonus != null) - reduction -= MathFunctions.CalculatePct(reduction, bonus.GetAmount()); - reduction *= (aurEff.GetTickNumber() - 1); - - MathFunctions.AddPct(ref damage, 6.0f - reduction); - aurEff.SetAmount((int)damage); - } - - public override void Register() - { - OnEffectUpdatePeriodic.Add(new(HandleTickUpdate, 0, AuraType.PeriodicHeal)); - } + return GetCaster().HasAura(SpellIds.EclipseLunarAura) || GetCaster().HasAura(SpellIds.EclipseSolarAura); } - [Script] // 145108 - Ysera's Gift - class spell_dru_yseras_gift : AuraScript + + void HandleDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.YserasGiftHealSelf, SpellIds.YserasGiftHealParty); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - int healAmount = (int)GetTarget().CountPctFromMaxHealth(aurEff.GetAmount()); - - if (!GetTarget().IsFullHealth()) - GetTarget().CastSpell(GetTarget(), SpellIds.YserasGiftHealSelf, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, healAmount)); - else - GetTarget().CastSpell(GetTarget(), SpellIds.YserasGiftHealParty, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, healAmount)); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } + AuraEffect umbralEmbrace = GetCaster().GetAuraEffect(SpellIds.UmbralEmbrace, 0); + if (umbralEmbrace != null) + MathFunctions.AddPct(ref pctMod, umbralEmbrace.GetAmount()); } - [Script] // 145110 - Ysera's Gift (heal) - class spell_dru_yseras_gift_group_heal : SpellScript + public override void Register() { - void SelectTargets(List targets) - { - SelectRandomInjuredTargets(targets, 1, true); - } + CalcDamage.Add(new(HandleDamage)); + } +} - public override void Register() +[Script] // Called by 393763 - Umbral Embrace +class spell_dru_umbral_inspiration : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UmbralInspirationTalent, SpellIds.UmbralInspirationAura); + } + + public override bool Load() + { + return GetUnitOwner().HasAura(SpellIds.UmbralInspirationTalent); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.UmbralInspirationAura, new CastSpellExtraArgs() { - OnObjectAreaTargetSelect.Add(new(SelectTargets, 0, Targets.UnitCasterAreaRaid)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 2, AuraType.Dummy)); + } +} + +[Script] // 377210 - Ursoc's Fury +class spell_dru_ursocs_fury : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UrsocsFuryShield); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + Unit caster = eventInfo.GetActor(); + int amount = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount()); + + caster.CastSpell(caster, SpellIds.UrsocsFuryShield, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, amount) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 48438 - Wild Growth +class spell_dru_wild_growth : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1), (SpellIds.TreeOfLife, 2)); + } + + void FilterTargets(List targets) + { + Unit caster = GetCaster(); + int maxTargets = GetEffectInfo(1).CalcValue(caster); + + AuraEffect treeOfLife = caster.GetAuraEffect(SpellIds.TreeOfLife, 2); + if (treeOfLife != null) + maxTargets += treeOfLife.GetAmount(); + + // Note: Wild Growth became a smart heal which prioritizes players and their pets in their group before any unit outside their group. + SelectRandomInjuredTargets(targets, (uint)maxTargets, true, caster); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +[Script] +class spell_dru_wild_growth_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RestorationT10_2PBonus); + } + + void HandleTickUpdate(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + // calculate from base damage, not from aurEff.GetAmount() (already modified) + float damage = caster.CalculateSpellDamage(GetUnitOwner(), aurEff.GetSpellEffectInfo()); + + // Wild Growth = first tick gains a 6% bonus, reduced by 2% each tick + float reduction = 2.0f; + AuraEffect bonus = caster.GetAuraEffect(SpellIds.RestorationT10_2PBonus, 0); + if (bonus != null) + reduction -= MathFunctions.CalculatePct(reduction, bonus.GetAmount()); + reduction *= (aurEff.GetTickNumber() - 1); + + MathFunctions.AddPct(ref damage, 6.0f - reduction); + aurEff.SetAmount((int)damage); + } + + public override void Register() + { + OnEffectUpdatePeriodic.Add(new(HandleTickUpdate, 0, AuraType.PeriodicHeal)); + } +} + +[Script] // 145108 - Ysera's Gift +class spell_dru_yseras_gift : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.YserasGiftHealSelf, SpellIds.YserasGiftHealParty); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + int healAmount = (int)GetTarget().CountPctFromMaxHealth(aurEff.GetAmount()); + + if (!GetTarget().IsFullHealth()) + GetTarget().CastSpell(GetTarget(), SpellIds.YserasGiftHealSelf, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, healAmount)); + else + GetTarget().CastSpell(GetTarget(), SpellIds.YserasGiftHealParty, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, healAmount)); + } + + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 145110 - Ysera's Gift (heal) +class spell_dru_yseras_gift_group_heal : SpellScript +{ + void SelectTargets(List targets) + { + SelectRandomInjuredTargets(targets, 1, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(SelectTargets, 0, Targets.UnitCasterAreaRaid)); } } \ No newline at end of file diff --git a/Source/Scripts/Spells/Evoker.cs b/Source/Scripts/Spells/Evoker.cs index f33c77220..67d1681ed 100644 --- a/Source/Scripts/Spells/Evoker.cs +++ b/Source/Scripts/Spells/Evoker.cs @@ -1,341 +1,742 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Framework.Dynamic; +using Game.AI; +using Game.DataStorage; using Game.Entities; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using static Global; -namespace Scripts.Spells.Evoker +namespace Scripts.Spells.Evoker; + +struct SpellIds { - enum SpellIds - { - BlastFurnace = 375510, - BlessingOfTheBronzeDk = 381732, - BlessingOfTheBronzeDh = 381741, - BlessingOfTheBronzeDruid = 381746, - BlessingOfTheBronzeEvoker = 381748, - BlessingOfTheBronzeHunter = 381749, - BlessingOfTheBronzeMage = 381750, - BlessingOfTheBronzeMonk = 381751, - BlessingOfTheBronzePaladin = 381752, - BlessingOfTheBronzePriest = 381753, - BlessingOfTheBronzeRogue = 381754, - BlessingOfTheBronzeShaman = 381756, - BlessingOfTheBronzeWarlock = 381757, - BlessingOfTheBronzeWarrior = 381758, - EnergizingFlame = 400006, - FireBreathDamage = 357209, - GlideKnockback = 358736, - Hover = 358267, - LivingFlame = 361469, - LivingFlameDamage = 361500, - LivingFlameHeal = 361509, - PermeatingChillTalent = 370897, - PyreDamage = 357212, - ScouringFlame = 378438, - SoarRacial = 369536, + public const uint AzureEssenceBurst = 375721; + public const uint BlastFurnace = 375510; + public const uint BlessingOfTheBronzeDk = 381732; + public const uint BlessingOfTheBronzeDh = 381741; + public const uint BlessingOfTheBronzeDruid = 381746; + public const uint BlessingOfTheBronzeEvoker = 381748; + public const uint BlessingOfTheBronzeHunter = 381749; + public const uint BlessingOfTheBronzeMage = 381750; + public const uint BlessingOfTheBronzeMonk = 381751; + public const uint BlessingOfTheBronzePaladin = 381752; + public const uint BlessingOfTheBronzePriest = 381753; + public const uint BlessingOfTheBronzeRogue = 381754; + public const uint BlessingOfTheBronzeShaman = 381756; + public const uint BlessingOfTheBronzeWarlock = 381757; + public const uint BlessingOfTheBronzeWarrior = 381758; + public const uint Burnout = 375802; + public const uint CallOfYseraTalent = 373834; + public const uint CallOfYsera = 373835; + public const uint Causality = 375777; + public const uint Disintegrate = 356995; + public const uint EmeraldBlossomHeal = 355916; + public const uint EnergizingFlame = 400006; + public const uint EssenceBurst = 359618; + public const uint FirestormDamage = 369374; + public const uint EternitySurge = 359073; + public const uint FireBreath = 357208; + public const uint FireBreathDamage = 357209; + public const uint GlideKnockback = 358736; + public const uint Hover = 358267; + public const uint LivingFlame = 361469; + public const uint LivingFlameDamage = 361500; + public const uint LivingFlameHeal = 361509; + public const uint PanaceaHeal = 387763; + public const uint PanaceaTalent = 387761; + public const uint PermeatingChillTalent = 370897; + public const uint PyreDamage = 357212; + public const uint RubyEmbers = 365937; + public const uint RubyEssenceBurst = 376872; + public const uint ScouringFlame = 378438; + public const uint Snapfire = 370818; + public const uint SoarRacial = 369536; + public const uint VerdantEmbraceHeal = 361195; + public const uint VerdantEmbraceJump = 373514; - LabelEvokerBlue = 1465 + public const uint LabelEvokerBlue = 1465; + + public const uint VisualKitEvokerVerdantEmbraceJump = 152557; + + public static uint[] CausalityAffectedEmpowerSpells = [EternitySurge, FireBreath]; +} + +[Script] // 362969 - Azure Strike (blue) +class spell_evo_azure_strike : SpellScript +{ + void FilterTargets(List targets) + { + targets.Remove(GetExplTargetUnit()); + targets.RandomResize((uint)GetEffectInfo(0).CalcValue(GetCaster()) - 1); + targets.Add(GetExplTargetUnit()); } - [Script] // 362969 - Azure Strike (blue) - class spell_evo_azure_strike : SpellScript + public override void Register() { - void FilterTargets(List targets) - { - targets.Remove(GetExplTargetUnit()); - targets.RandomResize((uint)GetEffectInfo(0).CalcValue(GetCaster()) - 1); - targets.Add(GetExplTargetUnit()); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); - } + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); } +} - // 381732 - Blessing of the Bronze (Bronze) - // 381741 - Blessing of the Bronze (Bronze) - // 381746 - Blessing of the Bronze (Bronze) - // 381748 - Blessing of the Bronze (Bronze) - // 381749 - Blessing of the Bronze (Bronze) - // 381750 - Blessing of the Bronze (Bronze) - // 381751 - Blessing of the Bronze (Bronze) - // 381752 - Blessing of the Bronze (Bronze) - // 381753 - Blessing of the Bronze (Bronze) - // 381754 - Blessing of the Bronze (Bronze) - // 381756 - Blessing of the Bronze (Bronze) - // 381757 - Blessing of the Bronze (Bronze) - [Script] // 381758 - Blessing of the Bronze (Bronze) - class spell_evo_blessing_of_the_bronze : SpellScript +// 381732 - Blessing of the Bronze (Bronze) +// 381741 - Blessing of the Bronze (Bronze) +// 381746 - Blessing of the Bronze (Bronze) +// 381748 - Blessing of the Bronze (Bronze) +// 381749 - Blessing of the Bronze (Bronze) +// 381750 - Blessing of the Bronze (Bronze) +// 381751 - Blessing of the Bronze (Bronze) +// 381752 - Blessing of the Bronze (Bronze) +// 381753 - Blessing of the Bronze (Bronze) +// 381754 - Blessing of the Bronze (Bronze) +// 381756 - Blessing of the Bronze (Bronze) +// 381757 - Blessing of the Bronze (Bronze) +[Script] // 381758 - Blessing of the Bronze (Bronze) +class spell_evo_blessing_of_the_bronze : SpellScript +{ + void RemoveInvalidTargets(List targets) { - void RemoveInvalidTargets(List targets) + targets.RemoveAll(target => { - targets.RemoveAll(target => + Unit unitTarget = target.ToUnit(); + if (unitTarget == null) + return true; + + switch (GetSpellInfo().Id) { - Unit unitTarget = target.ToUnit(); - if (unitTarget == null) - return true; - - return (SpellIds)GetSpellInfo().Id switch - { - SpellIds.BlessingOfTheBronzeDk => unitTarget.GetClass() != Class.Deathknight, - SpellIds.BlessingOfTheBronzeDh => unitTarget.GetClass() != Class.DemonHunter, - SpellIds.BlessingOfTheBronzeDruid => unitTarget.GetClass() != Class.Druid, - SpellIds.BlessingOfTheBronzeEvoker => unitTarget.GetClass() != Class.Evoker, - SpellIds.BlessingOfTheBronzeHunter => unitTarget.GetClass() != Class.Hunter, - SpellIds.BlessingOfTheBronzeMage => unitTarget.GetClass() != Class.Mage, - SpellIds.BlessingOfTheBronzeMonk => unitTarget.GetClass() != Class.Monk, - SpellIds.BlessingOfTheBronzePaladin => unitTarget.GetClass() != Class.Paladin, - SpellIds.BlessingOfTheBronzePriest => unitTarget.GetClass() != Class.Priest, - SpellIds.BlessingOfTheBronzeRogue => unitTarget.GetClass() != Class.Rogue, - SpellIds.BlessingOfTheBronzeShaman => unitTarget.GetClass() != Class.Shaman, - SpellIds.BlessingOfTheBronzeWarlock => unitTarget.GetClass() != Class.Warlock, - SpellIds.BlessingOfTheBronzeWarrior => unitTarget.GetClass() != Class.Warrior, - _ => true - }; - }); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(RemoveInvalidTargets, SpellConst.EffectAll, Targets.UnitCasterAreaRaid)); - } - } - - - [Script] // 370455 - Charged Blast - class spell_evo_charged_blast : AuraScript - { - bool CheckProc(ProcEventInfo procInfo) - { - return procInfo.GetSpellInfo() != null && procInfo.GetSpellInfo().HasLabel((uint)SpellIds.LabelEvokerBlue); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } - } - - // 357208 Fire Breath (Red) - [Script] // 382266 Fire Breath (Red) - class spell_evo_fire_breath : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo((uint)SpellIds.FireBreathDamage, (uint)SpellIds.BlastFurnace); - } - - void OnComplete(int completedStageCount) - { - int dotTicks = 10 - (completedStageCount - 1) * 3; - AuraEffect blastFurnace = GetCaster().GetAuraEffect((uint)SpellIds.BlastFurnace, 0); - if (blastFurnace != null) - dotTicks += blastFurnace.GetAmount() / 2; - - GetCaster().CastSpell(GetCaster(), (uint)SpellIds.FireBreathDamage, new CastSpellExtraArgs() - .SetTriggeringSpell(GetSpell()) - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .AddSpellMod(SpellValueModFloat.DurationPct, 100 * dotTicks) - .SetCustomArg(completedStageCount)); - } - - public override void Register() - { - OnEmpowerCompleted.Add(new(OnComplete)); - } - } - - [Script] // 357209 Fire Breath (Red) - class spell_evo_fire_breath_damage : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 2)) - && spellInfo.GetEffect(2).IsAura(AuraType.ModSilence); // validate we are removing the correct effect - } - - void AddBonusUpfrontDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - int empowerLevel = (int)GetSpell().m_customArg; - if (empowerLevel == 0) - return; - - // damage is done after aura is applied, grab periodic amount - AuraEffect fireBreath = victim.GetAuraEffect(GetSpellInfo().Id, 1, GetCaster().GetGUID()); - if (fireBreath != null) - flatMod += (int)(fireBreath.GetEstimatedAmount().GetValueOrDefault(fireBreath.GetAmount()) * (empowerLevel - 1) * 3); - } - - void RemoveUnusedEffect(List targets) - { - targets.Clear(); - } - - public override void Register() - { - CalcDamage.Add(new(AddBonusUpfrontDamage)); - OnObjectAreaTargetSelect.Add(new(RemoveUnusedEffect, 2, Targets.UnitConeCasterToDestEnemy)); - } - } - - [Script] // 358733 - Glide (Racial) - class spell_evo_glide : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo((uint)SpellIds.GlideKnockback, (uint)SpellIds.Hover, (uint)SpellIds.SoarRacial); - } - - SpellCastResult CheckCast() - { - Unit caster = GetCaster(); - - if (!caster.IsFalling()) - return SpellCastResult.NotOnGround; - - return SpellCastResult.SpellCastOk; - } - - void HandleCast() - { - Player caster = GetCaster().ToPlayer(); - if (caster == null) - return; - - caster.CastSpell(caster, (uint)SpellIds.GlideKnockback, true); - - caster.GetSpellHistory().StartCooldown(SpellMgr.GetSpellInfo((uint)SpellIds.Hover, GetCastDifficulty()), 0, null, false, TimeSpan.FromMilliseconds(250)); - caster.GetSpellHistory().StartCooldown(SpellMgr.GetSpellInfo((uint)SpellIds.SoarRacial, GetCastDifficulty()), 0, null, false, TimeSpan.FromMilliseconds(250)); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnCast.Add(new(HandleCast)); - } - } - - [Script] // 361469 - Living Flame (Red) - class spell_evo_living_flame : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo((uint)SpellIds.LivingFlameDamage, (uint)SpellIds.LivingFlameHeal, (uint)SpellIds.EnergizingFlame); - } - - void HandleHitTarget(uint effIndex) - { - Unit caster = GetCaster(); - Unit hitUnit = GetHitUnit(); - if (caster.IsFriendlyTo(hitUnit)) - caster.CastSpell(hitUnit, (uint)SpellIds.LivingFlameHeal, true); - else - caster.CastSpell(hitUnit, (uint)SpellIds.LivingFlameDamage, true); - } - - void HandleLaunchTarget(uint effIndex) - { - Unit caster = GetCaster(); - if (caster.IsFriendlyTo(GetHitUnit())) - return; - - AuraEffect auraEffect = caster.GetAuraEffect((uint)SpellIds.EnergizingFlame, 0); - if (auraEffect != null) - { - int manaCost = GetSpell().GetPowerTypeCostAmount(PowerType.Mana).GetValueOrDefault(0); - if (manaCost != 0) - GetCaster().ModifyPower(PowerType.Mana, MathFunctions.CalculatePct(manaCost, auraEffect.GetAmount())); + case SpellIds.BlessingOfTheBronzeDk: return unitTarget.GetClass() != Class.DeathKnight; + case SpellIds.BlessingOfTheBronzeDh: return unitTarget.GetClass() != Class.DemonHunter; + case SpellIds.BlessingOfTheBronzeDruid: return unitTarget.GetClass() != Class.Druid; + case SpellIds.BlessingOfTheBronzeEvoker: return unitTarget.GetClass() != Class.Evoker; + case SpellIds.BlessingOfTheBronzeHunter: return unitTarget.GetClass() != Class.Hunter; + case SpellIds.BlessingOfTheBronzeMage: return unitTarget.GetClass() != Class.Mage; + case SpellIds.BlessingOfTheBronzeMonk: return unitTarget.GetClass() != Class.Monk; + case SpellIds.BlessingOfTheBronzePaladin: return unitTarget.GetClass() != Class.Paladin; + case SpellIds.BlessingOfTheBronzePriest: return unitTarget.GetClass() != Class.Priest; + case SpellIds.BlessingOfTheBronzeRogue: return unitTarget.GetClass() != Class.Rogue; + case SpellIds.BlessingOfTheBronzeShaman: return unitTarget.GetClass() != Class.Shaman; + case SpellIds.BlessingOfTheBronzeWarlock: return unitTarget.GetClass() != Class.Warlock; + case SpellIds.BlessingOfTheBronzeWarrior: return unitTarget.GetClass() != Class.Warrior; + default: + break; } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHitTarget, 0, SpellEffectName.Dummy)); - OnEffectLaunchTarget.Add(new(HandleLaunchTarget, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 381773 - Permeating Chill - class spell_evo_permeating_chill : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo((uint)SpellIds.PermeatingChillTalent); - } - - bool CheckProc(ProcEventInfo procInfo) - { - SpellInfo spellInfo = procInfo.GetSpellInfo(); - if (spellInfo == null) - return false; - - if (spellInfo.HasLabel((uint)SpellIds.LabelEvokerBlue)) - return false; - - if (!procInfo.GetActor().HasAura((uint)SpellIds.PermeatingChillTalent)) - if (spellInfo.IsAffected(SpellFamilyNames.Evoker, new FlagArray128(0x40, 0, 0, 0))) // disintegrate - return false; - return true; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } + }); } - [Script] // 393568 - Pyre - class spell_evo_pyre : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo((uint)SpellIds.PyreDamage); - } - - void HandleDamage(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit().GetPosition(), (uint)SpellIds.PyreDamage, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDamage, 0, SpellEffectName.Dummy)); - } + OnObjectAreaTargetSelect.Add(new(RemoveInvalidTargets, SpellConst.EffectAll, Targets.UnitCasterAreaRaid)); } +} - [Script] // 357209 Fire Breath (Red) - class spell_evo_scouring_flame : SpellScript +[Script] // 375801 - Burnout +class spell_evo_burnout : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo((uint)SpellIds.ScouringFlame); - } + return ValidateSpellInfo(SpellIds.Burnout); + } - void HandleScouringFlame(List targets) - { - if (!GetCaster().HasAura((uint)SpellIds.ScouringFlame)) - targets.Clear(); - } + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } - void CalcDispelCount(uint effIndex) - { - int empowerLevel = (int)GetSpell().m_customArg; - if (empowerLevel != 0) - SetEffectValue(empowerLevel); - } + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.Burnout, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } - public override void Register() + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 373834 - Call of Ysera (attached to 361195 - Verdant Embrace (Green)) +class spell_evo_call_of_ysera : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CallOfYseraTalent, SpellIds.CallOfYsera); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.CallOfYseraTalent); + } + + void HandleCallOfYsera() + { + GetCaster().CastSpell(GetCaster(), SpellIds.CallOfYsera, new CastSpellExtraArgs() { - OnObjectAreaTargetSelect.Add(new(HandleScouringFlame, 3, Targets.UnitConeCasterToDestEnemy)); - OnEffectHitTarget.Add(new(CalcDispelCount, 3, SpellEffectName.Dispel)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleCallOfYsera)); + } +} + +[Script] // Called by 356995 - Disintegrate (Blue) +class spell_evo_causality_disintegrate : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.Causality, 1)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.Causality); + } + + void OnTick(AuraEffect aurEff) + { + AuraEffect causality = GetCaster().GetAuraEffect(SpellIds.Causality, 0); + if (causality != null) + { + foreach (uint spell in SpellIds.CausalityAffectedEmpowerSpells) + GetCaster().GetSpellHistory().ModifyCooldown(spell, TimeSpan.FromSeconds(causality.GetAmount())); } } -} \ No newline at end of file + + public override void Register() + { + OnEffectPeriodic.Add(new(OnTick, 0, AuraType.PeriodicDamage)); + } +} + +[Script] // Called by 357212 - Pyre (Red) +class spell_evo_causality_pyre : SpellScript +{ + static long TargetLimit = 5; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.Causality, 1)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.Causality); + } + + void HandleCooldown() + { + AuraEffect causality = GetCaster().GetAuraEffect(SpellIds.Causality, 1); + if (causality == null) + return; + + TimeSpan cooldownReduction = TimeSpan.FromSeconds(Math.Min(GetUnitTargetCountForEffect(0), TargetLimit) * causality.GetAmount()); + foreach (uint spell in SpellIds.CausalityAffectedEmpowerSpells) + GetCaster().GetSpellHistory().ModifyCooldown(spell, cooldownReduction); + } + + public override void Register() + { + AfterCast.Add(new(HandleCooldown)); + } +} + +[Script] // 370455 - Charged Blast +class spell_evo_charged_blast : AuraScript +{ + bool CheckProc(ProcEventInfo procInfo) + { + return procInfo.GetSpellInfo() != null && procInfo.GetSpellInfo().HasLabel(SpellIds.LabelEvokerBlue); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +// 355913 - Emerald Blossom (Green) +[Script] // Id - 23318 +class at_evo_emerald_blossom(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnRemove() + { + Unit caster = at.GetCaster(); + if (caster != null) + caster.CastSpell(at.GetPosition(), SpellIds.EmeraldBlossomHeal, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } +} + +[Script] // 355916 - Emerald Blossom (Green) +class spell_evo_emerald_blossom_heal : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void FilterTargets(List targets) + { + uint maxTargets = (uint)GetSpellInfo().GetEffect(1).CalcValue(GetCaster()); + SelectRandomInjuredTargets(targets, maxTargets, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +// Called by 362969 - Azure Strike +// Called by 361469 - Living Flame (Red) +[Script("spell_evo_azure_essence_burst", SpellIds.AzureEssenceBurst)] +[Script("spell_evo_ruby_essence_burst", SpellIds.RubyEssenceBurst)] +class spell_evo_essence_burst_trigger(uint talentAuraId) : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(talentAuraId, SpellIds.EssenceBurst); + } + + public override bool Load() + { + AuraEffect aurEff = GetCaster().GetAuraEffect(talentAuraId, 0); + return aurEff != null && RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleEssenceBurst() + { + GetCaster().CastSpell(GetCaster(), SpellIds.EssenceBurst, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleEssenceBurst)); + } +} + +// 357208 Fire Breath (Red) +[Script] // 382266 Fire Breath (Red) +class spell_evo_fire_breath : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FireBreathDamage, SpellIds.BlastFurnace); + } + + void OnComplete(int completedStageCount) + { + int dotTicks = 10 - (completedStageCount - 1) * 3; + AuraEffect blastFurnace = GetCaster().GetAuraEffect(SpellIds.BlastFurnace, 0); + if (blastFurnace != null) + dotTicks += blastFurnace.GetAmount() / 2; + + GetCaster().CastSpell(GetCaster(), SpellIds.FireBreathDamage, new CastSpellExtraArgs() + .SetTriggeringSpell(GetSpell()) + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .AddSpellMod(SpellValueModFloat.DurationPct, 100 * dotTicks) + .SetCustomArg(completedStageCount)); + } + + public override void Register() + { + OnEmpowerCompleted.Add(new(OnComplete)); + } +} + +[Script] // 357209 Fire Breath (Red) +class spell_evo_fire_breath_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 2)) + && spellInfo.GetEffect(2).IsAura(AuraType.ModSilence); // validate we are removing the correct effect + } + + void AddBonusUpfrontDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + var empowerLevel = (int)GetSpell().m_customArg; + if (empowerLevel == 0) + return; + + // damage is done after aura is applied, grab periodic amount + AuraEffect fireBreath = victim.GetAuraEffect(GetSpellInfo().Id, 1, GetCaster().GetGUID()); + if (fireBreath != null) + flatMod += (int)fireBreath.GetEstimatedAmount().GetValueOrDefault(fireBreath.GetAmount()) * (empowerLevel - 1) * 3; + } + + void RemoveUnusedEffect(List targets) + { + targets.Clear(); + } + + public override void Register() + { + CalcDamage.Add(new(AddBonusUpfrontDamage)); + OnObjectAreaTargetSelect.Add(new(RemoveUnusedEffect, 2, Targets.UnitConeCasterToDestEnemy)); + } +} + +[Script] // 369372 - Firestorm (Red) +class at_evo_firestorm(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TaskScheduler _scheduler = new(); + object _damageSpellCustomArg; + + public class extra_create_data + { + public float SnapshotDamageMultipliers = 1.0f; + } + + public static extra_create_data GetOrCreateExtraData(Spell firestorm) + { + if (firestorm.m_customArg.GetType() != typeof(extra_create_data)) + firestorm.m_customArg = new extra_create_data(); + + return (extra_create_data)firestorm.m_customArg; + } + + public override void OnCreate(Spell creatingSpell) + { + _damageSpellCustomArg = creatingSpell.m_customArg; + + _scheduler.Schedule(TimeSpan.FromSeconds(0), task => + { + TimeSpan period = TimeSpan.FromSeconds(2); // TimeSpan.FromSeconds(2), affected by haste + Unit caster = at.GetCaster(); + if (caster != null) + { + period *= caster.m_unitData.ModCastingSpeed; + caster.CastSpell(at.GetPosition(), SpellIds.FirestormDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + CustomArg = _damageSpellCustomArg + }); + } + + task.Repeat(period); + }); + } + + public override void OnUpdate(uint diff) + { + _scheduler.Update(diff); + } +} + +[Script] // 358733 - Glide (Racial) +class spell_evo_glide : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlideKnockback, SpellIds.Hover, SpellIds.SoarRacial); + } + + SpellCastResult CheckCast() + { + Unit caster = GetCaster(); + + if (!caster.IsFalling()) + return SpellCastResult.NotOnGround; + + return SpellCastResult.SpellCastOk; + } + + void HandleCast() + { + Player caster = GetCaster().ToPlayer(); + if (caster == null) + return; + + caster.CastSpell(caster, SpellIds.GlideKnockback, true); + + caster.GetSpellHistory().StartCooldown(Global.SpellMgr.GetSpellInfo(SpellIds.Hover, GetCastDifficulty()), 0, null, false, TimeSpan.FromSeconds(250)); + caster.GetSpellHistory().StartCooldown(Global.SpellMgr.GetSpellInfo(SpellIds.SoarRacial, GetCastDifficulty()), 0, null, false, TimeSpan.FromSeconds(250)); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnCast.Add(new(HandleCast)); + } +} + +[Script] // 361469 - Living Flame (Red) +class spell_evo_living_flame : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LivingFlameDamage, SpellIds.LivingFlameHeal, SpellIds.EnergizingFlame); + } + + void HandleHitTarget(uint effIndex) + { + Unit caster = GetCaster(); + Unit hitUnit = GetHitUnit(); + if (caster.IsValidAssistTarget(hitUnit)) + caster.CastSpell(hitUnit, SpellIds.LivingFlameHeal, true); + else + caster.CastSpell(hitUnit, SpellIds.LivingFlameDamage, true); + } + + void HandleLaunchTarget(uint effIndex) + { + Unit caster = GetCaster(); + if (caster.IsValidAssistTarget(GetHitUnit())) + return; + + AuraEffect auraEffect = caster.GetAuraEffect(SpellIds.EnergizingFlame, 0); + if (auraEffect != null) + { + int manaCost = GetSpell().GetPowerTypeCostAmount(PowerType.Mana).GetValueOrDefault(0); + if (manaCost != 0) + GetCaster().ModifyPower(PowerType.Mana, MathFunctions.CalculatePct(manaCost, auraEffect.GetAmount())); + } + } + + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHitTarget, 0, SpellEffectName.Dummy)); + OnEffectLaunchTarget.Add(new(HandleLaunchTarget, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 387761 Panacea (Green) (attached to 355913 - Emerald Blossom (Green) and 360995 - Verdant Embrace (Green)) +class spell_evo_panacea : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PanaceaTalent, SpellIds.PanaceaHeal); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.PanaceaTalent); + } + + void HandlePanacea() + { + GetCaster().CastSpell(GetCaster(), SpellIds.PanaceaHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandlePanacea)); + } +} + +[Script] // 381773 - Permeating Chill +class spell_evo_permeating_chill : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PermeatingChillTalent); + } + + bool CheckProc(ProcEventInfo procInfo) + { + SpellInfo spellInfo = procInfo.GetSpellInfo(); + if (spellInfo == null) + return false; + + if (!spellInfo.HasLabel(SpellIds.LabelEvokerBlue)) + return false; + + if (!procInfo.GetActor().HasAura(SpellIds.PermeatingChillTalent)) + if (!spellInfo.IsAffected(SpellFamilyNames.Evoker, new FlagArray128(0x40, 0, 0, 0))) // disintegrate + return false; + + return true; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] // 393568 - Pyre +class spell_evo_pyre : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PyreDamage); + } + + void HandleDamage(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit().GetPosition(), SpellIds.PyreDamage, true); + } + + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDamage, 0, SpellEffectName.Dummy)); + } +} + +// 361500 Living Flame (Red) +[Script] // 361509 Living Flame (Red) +class spell_evo_ruby_embers : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RubyEmbers) + && ValidateSpellEffect((spellInfo.Id, 1)) + && spellInfo.GetEffect(1).IsEffect(SpellEffectName.ApplyAura) + && spellInfo.GetEffect(1).ApplyAuraPeriod != 0; + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.RubyEmbers); + } + + + static void PreventPeriodic(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(PreventPeriodic, 1, m_scriptSpellId == SpellIds.LivingFlameDamage ? Targets.UnitTargetEnemy : Targets.UnitTargetAlly)); + } +} + +[Script] // 357209 Fire Breath (Red) +class spell_evo_scouring_flame : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ScouringFlame); + } + + void HandleScouringFlame(List targets) + { + if (!GetCaster().HasAura(SpellIds.ScouringFlame)) + targets.Clear(); + } + + void CalcDispelCount(uint effIndex) + { + int empowerLevel = (int)GetSpell().m_customArg; + if (empowerLevel != 0) + SetEffectValue(empowerLevel); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(HandleScouringFlame, 3, Targets.UnitConeCasterToDestEnemy)); + OnEffectHitTarget.Add(new(CalcDispelCount, 3, SpellEffectName.Dispel)); + } +} + +[Script] // Called by 368847 - Firestorm (Red) +class spell_evo_snapfire : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.Snapfire, 1)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.Snapfire); + } + + public override void OnPrecast() + { + AuraEffect snapfire = GetCaster().GetAuraEffect(SpellIds.Snapfire, 1); + if (snapfire != null) + if (GetSpell().m_appliedMods.Contains(snapfire.GetBase())) + MathFunctions.AddPct(ref at_evo_firestorm.GetOrCreateExtraData(GetSpell()).SnapshotDamageMultipliers, snapfire.GetAmount()); + } + + public override void Register() { } +} + +[Script] // Called by 369374 - Firestorm (Red) +class spell_evo_snapfire_bonus_damage : SpellScript +{ + void CalculateDamageBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + if (GetSpell().m_customArg is at_evo_firestorm.extra_create_data bonus) + pctMod *= bonus.SnapshotDamageMultipliers; + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamageBonus)); + } +} + +[Script] // 360995 - Verdant Embrace (Green) +class spell_evo_verdant_embrace : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VerdantEmbraceHeal, SpellIds.VerdantEmbraceJump) + && CliDB.SpellVisualKitStorage.HasRecord(SpellIds.VisualKitEvokerVerdantEmbraceJump); + } + + void HandleLaunchTarget(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + args.SetTriggeringSpell(GetSpell()); + + if (target != caster) + { + caster.CastSpell(target, SpellIds.VerdantEmbraceJump, args); + caster.SendPlaySpellVisualKit(SpellIds.VisualKitEvokerVerdantEmbraceJump, 0, 0); + } + else + caster.CastSpell(caster, SpellIds.VerdantEmbraceHeal, args); + } + + public override void Register() + { + OnEffectLaunchTarget.Add(new(HandleLaunchTarget, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 396557 - Verdant Embrace +class spell_evo_verdant_embrace_trigger_heal : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VerdantEmbraceHeal); + } + + void HandleHitTarget(uint effIndex) + { + GetHitUnit().CastSpell(GetExplTargetUnit(), SpellIds.VerdantEmbraceHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHitTarget, 0, SpellEffectName.Dummy)); + } +} diff --git a/Source/Scripts/Spells/Generic.cs b/Source/Scripts/Spells/Generic.cs index 241066140..a231dba37 100644 --- a/Source/Scripts/Spells/Generic.cs +++ b/Source/Scripts/Spells/Generic.cs @@ -1,5214 +1,5488 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +/* + * This file is part of the TrinityCore Project. See Authors file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the Gnu General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but Without + * Any Warranty; without even the implied warranty of Merchantability or + * Fitness For A Particular Purpose. See the Gnu General Public License for + * more details. + * + * You should have received a copy of the Gnu General Public License along + * with this program. If not, see . + */ + +/* + * Scripts for spells with SpellfamilyGeneric which cannot be included in Ai script file + * of creature using it or can't be bound to any player class. + * Ordered alphabetically using scriptname. + * Scriptnames of files in this file should be prefixed with "spell_gen_" + */ using Framework.Constants; using Framework.Dynamic; +using Game; +using Game.AI; using Game.DataStorage; using Game.Entities; using Game.Maps; using Game.Miscellaneous; +using Game.Movement; using Game.Networking.Packets; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; using System.Linq; -using static Global; -namespace Scripts.Spells.Generic +namespace Scripts.Spells.Generic; + +struct SpellIds { - [Script] - class spell_gen_absorb0_hitlimit1 : AuraScript + // AdaptiveWarding + public const uint GenAdaptiveWardingFire = 28765; + public const uint GenAdaptiveWardingNature = 28768; + public const uint GenAdaptiveWardingFrost = 28766; + public const uint GenAdaptiveWardingShadow = 28769; + public const uint GenAdaptiveWardingArcane = 28770; + + // AnimalBloodPoolSpell + public const uint AnimalBlood = 46221; + public const uint SpawnBloodPool = 63471; + + // GenericBandage + public const uint RecentlyBandaged = 11196; + + // BloodReserve + public const uint GenBloodReserveAura = 64568; + public const uint GenBloodReserveHeal = 64569; + + // Bonked + public const uint Bonked = 62991; + public const uint FoamSwordDefeat = 62994; + public const uint OnGuard = 62972; + + // BreakShieldSpells + public const uint BreakShieldDamage2K = 62626; + public const uint BreakShieldDamage10K = 64590; + public const uint BreakShieldTriggerFactionMounts = 62575; // Also on ToC5 mounts + public const uint BreakShieldTriggerCampaingWarhorse = 64595; + public const uint BreakShieldTriggerUnk = 66480; + + // CannibalizeSpells + public const uint CannibalizeTriggered = 20578; + + // ChaosBlast + public const uint ChaosBlast = 37675; + + // Clone + public const uint NightmareFigmentMirrorImage = 57528; + + // CloneWeaponSpells + public const uint CopyWeaponAura = 41054; + public const uint CopyWeapon2Aura = 63418; + public const uint CopyWeapon3Aura = 69893; + public const uint CopyOffhandAura = 45205; + public const uint CopyOffhand2Aura = 69896; + public const uint CopyRangedAura = 57594; + + // CreateLanceSpells + public const uint CreateLanceAlliance = 63914; + public const uint CreateLanceHorde = 63919; + + // DalaranDisguiseSpells + public const uint SunreaverDisguiseTrigger = 69672; + public const uint SunreaverDisguiseFemale = 70973; + public const uint SunreaverDisguiseMale = 70974; + + public const uint SilverCovenantDisguiseTrigger = 69673; + public const uint SilverCovenantDisguiseFemale = 70971; + public const uint SilverCovenantDisguiseMale = 70972; + + // DefendVisuals + public const uint VisualShield1 = 63130; + public const uint VisualShield2 = 63131; + public const uint VisualShield3 = 63132; + + // DivineStormSpell + public const uint DivineStorm = 53385; + + // EtherealPet + public const uint ProcTriggerOnKillAura = 50051; + public const uint EtherealPetAura = 50055; + public const uint CreateToken = 50063; + public const uint StealEssenceVisual = 50101; + + // Feast + public const uint GreatFeast = 57337; + public const uint FishFeast = 57397; + public const uint GiganticFeast = 58466; + public const uint SmallFeast = 58475; + public const uint BountifulFeast = 66477; + public const uint FeastFood = 45548; + public const uint FeastDrink = 57073; + public const uint BountifulFeastDrink = 66041; + public const uint BountifulFeastFood = 66478; + public const uint GreatFeastRefreshment = 57338; + public const uint FishFeastRefreshment = 57398; + public const uint GiganticFeastRefreshment = 58467; + public const uint SmallFeastRefreshment = 58477; + public const uint BountifulFeastRefreshment = 66622; + + // FuriousRage + public const uint Exhaustion = 35492; + + // FishingSpells + public const uint FishingNoFishingPole = 131476; + public const uint FishingWithPole = 131490; + + // TransporterBackfires + public const uint TransporterMalfunctionPolymorph = 23444; + public const uint TransporterEvilTwin = 23445; + public const uint TransporterMalfunctionMiss = 36902; + + // GnomishTransporter + public const uint TransporterSuccess = 23441; + public const uint TransporterFailure = 23446; + + // Interrupt + public const uint GenThrowInterrupt = 32747; + + // GenericLifebloom + public const uint HexlordMalacrassLifebloomFinalHeal = 43422; + public const uint TurRagepawLifebloomFinalHeal = 52552; + public const uint CenarionScoutLifebloomFinalHeal = 53692; + public const uint TwistedVisageLifebloomFinalHeal = 57763; + public const uint FactionChampionsDruLifebloomFinalHeal = 66094; + + // ChargeSpells + public const uint ChargeDamage8K5 = 62874; + public const uint ChargeDamage20K = 68498; + public const uint ChargeDamage45K = 64591; + public const uint ChargeChargingEffect8K5 = 63661; + public const uint ChargeCharging20K1 = 68284; + public const uint ChargeCharging20K2 = 68501; + public const uint ChargeChargingEffect45K1 = 62563; + public const uint ChargeChargingEffect45K2 = 66481; + public const uint ChargeTriggerFactionMounts = 62960; + public const uint ChargeTriggerTrialChampion = 68282; + public const uint ChargeMissEffect = 62977; + + // MossCoveredFeet + public const uint FallDown = 6869; + + // Netherbloom : uint + public const uint NetherbloomPollen1 = 28703; + + // NightmareVine + public const uint NightmarePollen = 28721; + + // ObsidianArmor + public const uint GenObsidianArmorHoly = 27536; + public const uint GenObsidianArmorFire = 27533; + public const uint GenObsidianArmorNature = 27538; + public const uint GenObsidianArmorFrost = 27534; + public const uint GenObsidianArmorShadow = 27535; + public const uint GenObsidianArmorArcane = 27540; + + // OrcDisguiseSpells + public const uint OrcDisguiseTrigger = 45759; + public const uint OrcDisguiseMale = 45760; + public const uint OrcDisguiseFemale = 45762; + + // ParalyticPoison + public const uint Paralysis = 35202; + + // ParachuteSpells + public const uint Parachute = 45472; + public const uint ParachuteBuff = 44795; + + // ProfessionResearch + public const uint NorthrendInscriptionResearch = 61177; + + // TrinketSpells + public const uint PvpTrinketAlliance = 97403; + public const uint PvpTrinketHorde = 97404; + + // Replenishment + public const uint Replenishment = 57669; + public const uint InfiniteReplenishment = 61782; + + // RunningWildMountIds + public const uint AlteredForm = 97709; + + // SeaforiumSpells + public const uint PlantChargesCreditAchievement = 60937; + + // TournamentMountsSpells + public const uint LanceEquipped = 62853; + + // MountedDuelSpells + public const uint OnTournamentMount = 63034; + public const uint MountedDuel = 62875; + + // Teleporting + public const uint TeleportSpireDown = 59316; + public const uint TeleportSpireUp = 59314; + + // PvPTrinketTriggeredSpells + public const uint WillOfTheForsakenCooldownTrigger = 72752; + public const uint WillOfTheForsakenCooldownTriggerWotf = 72757; + + // FriendOrFowl + public const uint TurkeyVengeance = 25285; + + // VampiricTouch + public const uint VampiricTouchHeal = 52724; + + // VehicleScaling + public const uint GearScaling = 66668; + + // WhisperGulchYoggSaronWhisper + public const uint YoggSaronWhisperDummy = 29072; + + // GMFreeze + public const uint GmFreeze = 9454; + + // RequiredMixologySpells + public const uint Mixology = 53042; + // Flasks + public const uint FlaskOfTheFrostWyrm = 53755; + public const uint FlaskOfStoneblood = 53758; + public const uint FlaskOfEndlessRage = 53760; + public const uint FlaskOfPureMojo = 54212; + public const uint LesserFlaskOfResistance = 62380; + public const uint LesserFlaskOfToughness = 53752; + public const uint FlaskOfBlindingLight = 28521; + public const uint FlaskOfChromaticWonder = 42735; + public const uint FlaskOfFortification = 28518; + public const uint FlaskOfMightyRestoration = 28519; + public const uint FlaskOfPureDeath = 28540; + public const uint FlaskOfRelentlessAssault = 28520; + public const uint FlaskOfChromaticResistance = 17629; + public const uint FlaskOfDistilledWisdom = 17627; + public const uint FlaskOfSupremePower = 17628; + public const uint FlaskOfTheTitans = 17626; + // Elixirs + public const uint ElixirOfMightyAgility = 28497; + public const uint ElixirOfAccuracy = 60340; + public const uint ElixirOfDeadlyStrikes = 60341; + public const uint ElixirOfMightyDefense = 60343; + public const uint ElixirOfExpertise = 60344; + public const uint ElixirOfArmorPiercing = 60345; + public const uint ElixirOfLightningSpeed = 60346; + public const uint ElixirOfMightyFortitude = 53751; + public const uint ElixirOfMightyMageblood = 53764; + public const uint ElixirOfMightyStrength = 53748; + public const uint ElixirOfMightyToughts = 60347; + public const uint ElixirOfProtection = 53763; + public const uint ElixirOfSpirit = 53747; + public const uint GurusElixir = 53749; + public const uint ShadowpowerElixir = 33721; + public const uint WrathElixir = 53746; + public const uint ElixirOfEmpowerment = 28514; + public const uint ElixirOfMajorMageblood = 28509; + public const uint ElixirOfMajorShadowPower = 28503; + public const uint ElixirOfMajorDefense = 28502; + public const uint FelStrengthElixir = 38954; + public const uint ElixirOfIronskin = 39628; + public const uint ElixirOfMajorAgility = 54494; + public const uint ElixirOfDraenicWisdom = 39627; + public const uint ElixirOfMajorFirepower = 28501; + public const uint ElixirOfMajorFrostPower = 28493; + public const uint EarthenElixir = 39626; + public const uint ElixirOfMastery = 33726; + public const uint ElixirOfHealingPower = 28491; + public const uint ElixirOfMajorFortitude = 39625; + public const uint ElixirOfMajorStrength = 28490; + public const uint AdeptsElixir = 54452; + public const uint OnslaughtElixir = 33720; + public const uint MightyTrollsBloodElixir = 24361; + public const uint GreaterArcaneElixir = 17539; + public const uint ElixirOfTheMongoose = 17538; + public const uint ElixirOfBruteForce = 17537; + public const uint ElixirOfSages = 17535; + public const uint ElixirOfSuperiorDefense = 11348; + public const uint ElixirOfDemonslaying = 11406; + public const uint ElixirOfGreaterFirepower = 26276; + public const uint ElixirOfShadowPower = 11474; + public const uint MagebloodElixir = 24363; + public const uint ElixirOfGiants = 11405; + public const uint ElixirOfGreaterAgility = 11334; + public const uint ArcaneElixir = 11390; + public const uint ElixirOfGreaterIntellect = 11396; + public const uint ElixirOfGreaterDefense = 11349; + public const uint ElixirOfFrostPower = 21920; + public const uint ElixirOfAgility = 11328; + public const uint MajorTrollsBlloodElixir = 3223; + public const uint ElixirOfFortitude = 3593; + public const uint ElixirOfOgresStrength = 3164; + public const uint ElixirOfFirepower = 7844; + public const uint ElixirOfLesserAgility = 3160; + public const uint ElixirOfDefense = 3220; + public const uint StrongTrollsBloodElixir = 3222; + public const uint ElixirOfMinorAccuracy = 63729; + public const uint ElixirOfWisdom = 3166; + public const uint ElixirOfGianthGrowth = 8212; + public const uint ElixirOfMinorAgility = 2374; + public const uint ElixirOfMinorFortitude = 2378; + public const uint WeakTrollsBloodElixir = 3219; + public const uint ElixirOfLionsStrength = 2367; + public const uint ElixirOfMinorDefense = 673; + + // LandmineKnockbackAchievement + public const uint LandmineKnockbackAchievement = 57064; + + // CorruptinPlagueEntrys + public const uint CorruptingPlague = 40350; + + // StasisFieldEntrys + public const uint StasisField = 40307; + + // SiegeTankControl + public const uint SiegeTankControl = 47963; + + // FreezingCircleMisc + public const uint FreezingCirclePitOfSaronNormal = 69574; + public const uint FreezingCirclePitOfSaronHeroic = 70276; + public const uint FreezingCircle = 34787; + public const uint FreezingCircleScenario = 141383; + + // CannonBlast + public const uint CannonBlast = 42578; + public const uint CannonBlastDamage = 42576; + + // KazrogalHellfireMark + public const uint MarkOfKazrogalHellfire = 189512; + public const uint MarkOfKazrogalDamageHellfire = 189515; + + // AuraProcRemoveSpells + public const uint FaceRage = 99947; + public const uint ImpatientMind = 187213; + + // DefenderOfAzerothData + public const uint DeathGateTeleportStormwind = 316999; + public const uint DeathGateTeleportOrgrimmar = 317000; + + // AncestralCallSpells + public const uint RictusOfTheLaughingSkull = 274739; + public const uint ZealOfTheBurningBlade = 274740; + public const uint FerocityOfTheFrostwolf = 274741; + public const uint MightOfTheBlackrock = 274742; + + // SkinningLearningSpell + public const uint ClassicSkinning = 265856; + public const uint OutlandSkinning = 265858; + public const uint NorthrendSkinning = 265860; + public const uint CataclysmSkinning = 265862; + public const uint PandariaSkinning = 265864; + public const uint DraenorSkinning = 265866; + public const uint LegionSkinning = 265868; + public const uint KulTiranSkinning = 265870; + public const uint ZandalariSkinning = 265872; + public const uint ShadowlandsSkinning = 308570; + public const uint DragonIslesSkinning = 366263; + + // BloodlustExhaustionSpell + public const uint ShamanSated = 57724; // Bloodlust + public const uint ShamanExhaustion = 57723; // Heroism; Drums + public const uint MageTemporalDisplacement = 80354; + public const uint HunterFatigued = 264689; + public const uint EvokerExhaustion = 390435; + + // MajorHealingCooldownSpell + public const uint DruidTranquility = 740; + public const uint DruidTranquilityHeal = 157982; + public const uint PriestDivineHymn = 64843; + public const uint PriestDivineHymnHeal = 64844; + public const uint PriestLuminousBarrier = 271466; + public const uint ShamanHealingTideTotem = 108280; + public const uint ShamanHealingTideTotemHeal = 114942; + public const uint MonkRevival = 115310; + public const uint EvokerRewind = 363534; + + // SpatialRiftSpells + public const uint SpatialRiftTeleport = 257034; + public const uint SpatialRiftAreatrigger = 256948; +} + +struct CreatureIds +{ + // EtherealPet + public const uint EtherealSoulTrader = 27914; + + // PetSummoned + public const uint Doomguard = 11859; + public const uint Infernal = 89; + public const uint Imp = 416; + + // VendorBarkTrigger + public const uint AmphitheaterVendor = 30098; + + // CorruptinPlagueEntrys + public const uint ApexisFlayer = 22175; + public const uint ShardHideBoar = 22180; + public const uint AetherRay = 22181; + + // StasisFieldEntrys + public const uint DaggertailLizard = 22255; + + // DefenderOfAzerothData + public const uint Nazgrim = 161706; + public const uint Trollbane = 161707; + public const uint Whitemane = 161708; + public const uint Mograine = 161709; +} + +struct MiscConst +{ + // EtherealPet + public const uint SayStealEssence = 1; + public const uint SayCreateToken = 2; + + + // FuriousRage + public const uint EmoteFuriousRage = 19415; + public const uint EmoteExhausted = 18368; + + + // Teleporting + public const uint AreaVioletCitadelSpire = 4637; + + // FoamSword + public const uint ItemFoamSwordGreen = 45061; + public const uint ItemFoamSwordPink = 45176; + public const uint ItemFoamSwordBlue = 45177; + public const uint ItemFoamSwordRed = 45178; + public const uint ItemFoamSwordYellow = 45179; + + // VendorBarkTrigger + public const uint SayAmphitheaterVendor = 0; + + // WhisperToControllerTexts + public const uint WhisperFutureYou = 2; + public const uint WhisperDefender = 1; + public const uint WhisperPastYou = 2; + + // PonySpells + public const uint AchievPonyUp = 3736; + public const uint MountPony = 29736; + + // FreezingCircleMisc + public const uint MapIdBloodInTheSnowScenario = 1130; + + // DefenderOfAzerothData + public const uint QuestDefenderOfAzerothAlliance = 58902; + public const uint QuestDefenderOfAzerothHorde = 58903; + + public static float GetBonusMultiplier(Unit unit, uint spellId) { - uint limit; - - public override bool Load() + // Note: if caster is not in a raid setting, is in PvP or while in arena combat with 5 or less allied players. + if (!unit.GetMap().IsRaid() || !unit.GetMap().IsBattleground()) { - // Max absorb stored in 1 dummy effect - limit = (uint)GetSpellInfo().GetEffect(1).CalcValue(); - return true; - } - - void Absorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - absorbAmount = Math.Min(limit, absorbAmount); - } - - public override void Register() - { - OnEffectAbsorb.Add(new(Absorb, 0)); - } - } - - [Script] // 28764 - Adaptive Warding (Frostfire Regalia Set) - class spell_gen_adaptive_warding : AuraScript - { - const uint SpellGenAdaptiveWardingFire = 28765; - const uint SpellGenAdaptiveWardingNature = 28768; - const uint SpellGenAdaptiveWardingFrost = 28766; - const uint SpellGenAdaptiveWardingShadow = 28769; - const uint SpellGenAdaptiveWardingArcane = 28770; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellGenAdaptiveWardingFire, SpellGenAdaptiveWardingNature, SpellGenAdaptiveWardingFrost, SpellGenAdaptiveWardingShadow, SpellGenAdaptiveWardingArcane); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - if (eventInfo.GetSpellInfo() == null) - return false; - - // find Mage Armor - if (GetTarget().GetAuraEffect(AuraType.ModManaRegenInterrupt, SpellFamilyNames.Mage, new FlagArray128(0x10000000, 0x0, 0x0)) == null) - return false; - - return SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask()) switch + uint bonusSpellId = 0; + uint effIndex = 0; + switch (spellId) { - SpellSchools.Normal or SpellSchools.Holy => false, - _ => true - }; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - uint spellId = SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask()) switch - { - SpellSchools.Fire => SpellGenAdaptiveWardingFire, - SpellSchools.Nature => SpellGenAdaptiveWardingNature, - SpellSchools.Frost => SpellGenAdaptiveWardingFrost, - SpellSchools.Shadow => SpellGenAdaptiveWardingShadow, - SpellSchools.Arcane => SpellGenAdaptiveWardingArcane, - _ => 0 - }; - - if (spellId != 0) - GetTarget().CastSpell(GetTarget(), spellId, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] - class spell_gen_allow_cast_from_item_only : SpellScript - { - SpellCastResult CheckRequirement() - { - if (GetCastItem() == null) - return SpellCastResult.CantDoThatRightNow; - - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckRequirement)); - } - } - - [Script] // 46221 - Animal Blood - class spell_gen_animal_blood : AuraScript - { - const uint SpellAnimalBlood = 46221; - const uint SpellSpawnBloodPool = 63471; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellSpawnBloodPool); - } - - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // Remove all auras with spell id 46221, except the one currently being applied - Aura aur; - while ((aur = GetUnitOwner().GetOwnedAura(SpellAnimalBlood, ObjectGuid.Empty, ObjectGuid.Empty, 0, GetAura())) != null) - GetUnitOwner().RemoveOwnedAura(aur); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit owner = GetUnitOwner(); - if (owner != null) - owner.CastSpell(owner, SpellSpawnBloodPool, true); - } - - public override void Register() - { - AfterEffectApply.Add(new(OnApply, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - [Script] // 63471 - Spawn Blood Pool - class spell_spawn_blood_pool : SpellScript - { - void SetDest(ref SpellDestination dest) - { - Unit caster = GetCaster(); - Position summonPos = caster.GetPosition(); - LiquidData liquidStatus; - if (caster.GetMap().GetLiquidStatus(caster.GetPhaseShift(), caster.GetPositionX(), caster.GetPositionY(), caster.GetPositionZ(), out liquidStatus, null, caster.GetCollisionHeight()) != ZLiquidStatus.NoWater) - summonPos.posZ = liquidStatus.level; - dest.Relocate(summonPos); - } - - public override void Register() - { - OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCaster)); - } - } - - // 430 Drink - // 431 Drink - // 432 Drink - // 1133 Drink - // 1135 Drink - // 1137 Drink - // 10250 Drink - // 22734 Drink - // 27089 Drink - // 34291 Drink - // 43182 Drink - // 43183 Drink - // 46755 Drink - // 49472 Drink Coffee - // 57073 Drink - // 61830 Drink - [Script] // 72623 Drink - class spell_gen_arena_drink : AuraScript - { - public override bool Load() - { - return GetCaster() != null && GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spellInfo) - { - if (!ValidateSpellEffect((spellInfo.Id, 0)) || !spellInfo.GetEffect(0).IsAura(AuraType.ModPowerRegen)) - { - Log.outError(LogFilter.Spells, $"Aura {GetId()} structure has been changed - first aura is no longer AuraType.ModPowerRegen"); - return false; - } - - return true; - } - - void CalcPeriodic(AuraEffect aurEff, ref bool isPeriodic, ref int amplitude) - { - // Get AuraType.ModPowerRegen aura from spell - AuraEffect regen = GetAura().GetEffect(0); - if (regen == null) - return; - - // default case - not in arena - if (!GetCaster().ToPlayer().InArena()) - isPeriodic = false; - } - - void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - AuraEffect regen = GetAura().GetEffect(0); - if (regen == null) - return; - - // default case - not in arena - if (!GetCaster().ToPlayer().InArena()) - regen.ChangeAmount(amount); - } - - void UpdatePeriodic(AuraEffect aurEff) - { - AuraEffect regen = GetAura().GetEffect(0); - if (regen == null) - return; - - // ********************************************** - // This feature used only in arenas - // ********************************************** - // Here need increase mana regen per tick (6 second rule) - // on 0 tick - 0 (handled in 2 second) - // on 1 tick - 166% (handled in 4 second) - // on 2 tick - 133% (handled in 6 second) - - // Apply bonus for 1 - 4 tick - switch (aurEff.GetTickNumber()) - { - case 1: // 0% - regen.ChangeAmount(0); + case SpellIds.DruidTranquilityHeal: + bonusSpellId = SpellIds.DruidTranquility; + effIndex = 2; break; - case 2: // 166% - regen.ChangeAmount(aurEff.GetAmount() * 5 / 3); + case SpellIds.PriestDivineHymnHeal: + bonusSpellId = SpellIds.PriestDivineHymn; + effIndex = 1; break; - case 3: // 133% - regen.ChangeAmount(aurEff.GetAmount() * 4 / 3); + case SpellIds.PriestLuminousBarrier: + bonusSpellId = spellId; + effIndex = 1; break; - default: // 100% - normal regen - regen.ChangeAmount(aurEff.GetAmount()); - // No need to update after 4th tick - aurEff.SetPeriodic(false); + case SpellIds.ShamanHealingTideTotemHeal: + bonusSpellId = SpellIds.ShamanHealingTideTotem; + effIndex = 2; + break; + case SpellIds.MonkRevival: + bonusSpellId = spellId; + effIndex = 4; + break; + case SpellIds.EvokerRewind: + bonusSpellId = spellId; + effIndex = 3; break; - } - } - - public override void Register() - { - DoEffectCalcPeriodic.Add(new(CalcPeriodic, 1, AuraType.PeriodicDummy)); - DoEffectCalcAmount.Add(new(CalcAmount, 1, AuraType.PeriodicDummy)); - OnEffectUpdatePeriodic.Add(new(UpdatePeriodic, 1, AuraType.PeriodicDummy)); - } - } - - [Script] // 28313 - Aura of Fear - class spell_gen_aura_of_fear : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 0)) && ValidateSpellInfo(spellInfo.GetEffect(0).TriggerSpell); - } - - void PeriodicTick(AuraEffect aurEff) - { - PreventDefaultAction(); - if (!RandomHelper.randChance(GetSpellInfo().ProcChance)) - return; - - GetTarget().CastSpell(null, aurEff.GetSpellEffectInfo().TriggerSpell, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicTriggerSpell)); - } - } - - [Script] - class spell_gen_av_drekthar_presence : AuraScript - { - bool CheckAreaTarget(Unit target) - { - switch (target.GetEntry()) - { - // alliance - case 14762: // Dun Baldar North Marshal - case 14763: // Dun Baldar South Marshal - case 14764: // Icewing Marshal - case 14765: // Stonehearth Marshal - case 11948: // Vandar Stormspike - // horde - case 14772: // East Frostwolf Warmaster - case 14776: // Tower Point Warmaster - case 14773: // Iceblood Warmaster - case 14777: // West Frostwolf Warmaster - case 11946: // Drek'thar - return true; default: - return false; + return 0.0f; } + + AuraEffect healingIncreaseEffect = unit.GetAuraEffect(bonusSpellId, effIndex); + if (healingIncreaseEffect != null) + return healingIncreaseEffect.GetAmount(); + + return Global.SpellMgr.GetSpellInfo(bonusSpellId, Difficulty.None).GetEffect(effIndex).CalcValue(unit); } - public override void Register() + return 0.0f; + } +} + +[Script] +class spell_gen_absorb0_hitlimit1 : AuraScript +{ + uint limit = 0; + + public override bool Load() + { + // Max absorb stored in 1 dummy effect + limit = (uint)GetSpellInfo().GetEffect(1).CalcValue(); + return true; + } + + void Absorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + absorbAmount = Math.Min(limit, absorbAmount); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(Absorb, 0)); + } +} + +[Script] +class spell_gen_adaptive_warding : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GenAdaptiveWardingFire, SpellIds.GenAdaptiveWardingNature, SpellIds.GenAdaptiveWardingFrost, SpellIds.GenAdaptiveWardingShadow, SpellIds.GenAdaptiveWardingArcane); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetSpellInfo() == null) + return false; + + // find Mage Armor + if (GetTarget().GetAuraEffect(AuraType.ModManaRegenInterrupt, SpellFamilyNames.Mage, new FlagArray128(0x10000000, 0x0, 0x0)) == null) + return false; + + switch (SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask())) { - DoCheckAreaTarget.Add(new(CheckAreaTarget)); + case SpellSchools.Normal: + case SpellSchools.Holy: + return false; + default: + break; + } + return true; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + uint spellId = 0; + switch (SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask())) + { + case SpellSchools.Fire: + spellId = SpellIds.GenAdaptiveWardingFire; + break; + case SpellSchools.Nature: + spellId = SpellIds.GenAdaptiveWardingNature; + break; + case SpellSchools.Frost: + spellId = SpellIds.GenAdaptiveWardingFrost; + break; + case SpellSchools.Shadow: + spellId = SpellIds.GenAdaptiveWardingShadow; + break; + case SpellSchools.Arcane: + spellId = SpellIds.GenAdaptiveWardingArcane; + break; + default: + return; + } + GetTarget().CastSpell(GetTarget(), spellId, aurEff); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] +class spell_gen_allow_cast_from_item_only : SpellScript +{ + SpellCastResult CheckRequirement() + { + if (GetCastItem() == null) + return SpellCastResult.CantDoThatRightNow; + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckRequirement)); + } +} + +[Script] // 46221 - Animal Blood +class spell_gen_animal_blood : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SpawnBloodPool); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // Remove all auras with spell id 46221, except the one currently being applied + Aura aur; + while ((aur = GetUnitOwner().GetOwnedAura(SpellIds.AnimalBlood, ObjectGuid.Empty, ObjectGuid.Empty, 0, GetAura())) != null) + GetUnitOwner().RemoveOwnedAura(aur); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit owner = GetUnitOwner(); + if (owner != null) + owner.CastSpell(owner, SpellIds.SpawnBloodPool, true); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnApply, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 63471 - Spawn Blood Pool +class spell_spawn_blood_pool : SpellScript +{ + void SetDest(ref SpellDestination dest) + { + Unit caster = GetCaster(); + Position summonPos = caster.GetPosition(); + LiquidData liquidStatus; + if (caster.GetMap().GetLiquidStatus(caster.GetPhaseShift(), caster.GetPositionX(), caster.GetPositionY(), caster.GetPositionZ(), out liquidStatus, null, caster.GetCollisionHeight()) != ZLiquidStatus.NoWater) + summonPos.posZ = liquidStatus.level; + dest.Relocate(summonPos); + } + + public override void Register() + { + OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCaster)); + } +} + +// 430 Drink +// 431 Drink +// 432 Drink +// 1133 Drink +// 1135 Drink +// 1137 Drink +// 10250 Drink +// 22734 Drink +// 27089 Drink +// 34291 Drink +// 43182 Drink +// 43183 Drink +// 46755 Drink +// 49472 Drink Coffee +// 57073 Drink +// 61830 Drink +[Script] // 72623 Drink +class spell_gen_arena_drink : AuraScript +{ + public override bool Load() + { + return GetCaster() != null && GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + if (!ValidateSpellEffect((spellInfo.Id, 0)) || !spellInfo.GetEffect(0).IsAura(AuraType.ModPowerRegen)) + { + Log.outError(LogFilter.Spells, $"Aura {GetId()} structure has been changed - first aura is no longer SpellAuraModPowerRegen"); + return false; + } + + return true; + } + + void CalcPeriodic(AuraEffect aurEff, ref bool isPeriodic, ref int amplitude) + { + // Get SpellAuraModPowerRegen aura from spell + AuraEffect regen = GetAura().GetEffect(0); + if (regen == null) + return; + + // default case - not in arena + if (!GetCaster().ToPlayer().InArena()) + isPeriodic = false; + } + + void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + AuraEffect regen = GetAura().GetEffect(0); + if (regen == null) + return; + + // default case - not in arena + if (!GetCaster().ToPlayer().InArena()) + regen.ChangeAmount(amount); + } + + void UpdatePeriodic(AuraEffect aurEff) + { + AuraEffect regen = GetAura().GetEffect(0); + if (regen == null) + return; + + // ********************************************** + // This feature used only in arenas + // ********************************************** + // Here need increase mana regen per tick (6 second rule) + // on 0 tick - 0 (handled in 2 second) + // on 1 tick - 166% (handled in 4 second) + // on 2 tick - 133% (handled in 6 second) + + // Apply bonus for 1 - 4 tick + switch (aurEff.GetTickNumber()) + { + case 1: // 0% + regen.ChangeAmount(0); + break; + case 2: // 166% + regen.ChangeAmount(aurEff.GetAmount() * 5 / 3); + break; + case 3: // 133% + regen.ChangeAmount(aurEff.GetAmount() * 4 / 3); + break; + default: // 100% - normal regen + regen.ChangeAmount(aurEff.GetAmount()); + // No need to update after 4th tick + aurEff.SetPeriodic(false); + break; } } - [Script] - class spell_gen_bandage : SpellScript + public override void Register() { - const uint SpellRecentlyBandaged = 11196; - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellRecentlyBandaged); - } + DoEffectCalcPeriodic.Add(new(CalcPeriodic, 1, AuraType.PeriodicDummy)); + DoEffectCalcAmount.Add(new(CalcAmount, 1, AuraType.PeriodicDummy)); + OnEffectUpdatePeriodic.Add(new(UpdatePeriodic, 1, AuraType.PeriodicDummy)); + } +} - SpellCastResult CheckCast() - { - Unit target = GetExplTargetUnit(); - if (target != null) - { - if (target.HasAura(SpellRecentlyBandaged)) - return SpellCastResult.TargetAurastate; - } - return SpellCastResult.SpellCastOk; - } +[Script] // 28313 - Aura of Fear +class spell_gen_aura_of_fear : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 0)) && ValidateSpellInfo(spellInfo.GetEffect(0).TriggerSpell); + } - void HandleScript() - { - Unit target = GetHitUnit(); - if (target != null) - GetCaster().CastSpell(target, SpellRecentlyBandaged, true); - } + void PeriodicTick(AuraEffect aurEff) + { + PreventDefaultAction(); + if (!RandomHelper.randChance(GetSpellInfo().ProcChance)) + return; - public override void Register() + GetTarget().CastSpell(null, aurEff.GetSpellEffectInfo().TriggerSpell, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] +class spell_gen_av_drekthar_presence : AuraScript +{ + bool CheckAreaTarget(Unit target) + { + switch (target.GetEntry()) { - OnCheckCast.Add(new(CheckCast)); - AfterHit.Add(new(HandleScript)); + // alliance + case 14762: // Dun Baldar North Marshal + case 14763: // Dun Baldar South Marshal + case 14764: // Icewing Marshal + case 14765: // Stonehearth Marshal + case 11948: // Vandar Stormspike + // horde + case 14772: // East Frostwolf Warmaster + case 14776: // Tower Point Warmaster + case 14773: // Iceblood Warmaster + case 14777: // West Frostwolf Warmaster + case 11946: // Drek'thar + return true; + default: + return false; } } - [Script] // 193970 - Mercenary Shapeshift - class spell_gen_battleground_mercenary_shapeshift : AuraScript + public override void Register() { - List RacialSkills = new(); + DoCheckAreaTarget.Add(new(CheckAreaTarget)); + } +} - Dictionary RaceDisplayIds = new() - { - { Race.Human , new uint[] { 55239, 55238 } }, - { Race.Orc , new uint[] { 55257, 55256 } }, - { Race.Dwarf , new uint[] { 55241, 55240 } }, - { Race.NightElf , new uint[] { 55243, 55242 } }, - { Race.Undead , new uint[] { 55259, 55258 } }, - { Race.Tauren , new uint[] { 55261, 55260 } }, - { Race.Gnome , new uint[] { 55245, 55244 } }, - { Race.Troll , new uint[] { 55263, 55262 } }, - { Race.Goblin , new uint[] { 55267, 57244 } }, - { Race.BloodElf , new uint[] { 55265, 55264 } }, - { Race.Draenei , new uint[] { 55247, 55246 } }, - { Race.Worgen , new uint[] { 55255, 55254 } }, - { Race.PandarenNeutral , new uint[] { 55253, 55252 } }, // not verified, might be swapped with RacePandarenHorde - { Race.PandarenAlliance , new uint[] { 55249, 55248 } }, - { Race.PandarenHorde , new uint[] { 55251, 55250 } }, - { Race.Nightborne , new uint[] { 82375, 82376 } }, - { Race.HighmountainTauren , new uint[] { 82377, 82378 } }, - { Race.VoidElf , new uint[] { 82371, 82372 } }, - { Race.LightforgedDraenei , new uint[] { 82373, 82374 } }, - { Race.ZandalariTroll , new uint[] { 88417, 88416 } }, - { Race.KulTiran , new uint[] { 88414, 88413 } }, - { Race.DarkIronDwarf , new uint[] { 88409, 88408 } }, - { Race.Vulpera , new uint[] { 94999, 95001 } }, - { Race.MagharOrc , new uint[] { 88420, 88410 } }, - { Race.MechaGnome , new uint[] { 94998, 95000 } }, - }; +[Script] +class spell_gen_bandage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RecentlyBandaged); + } - Race GetReplacementRace(Race nativeRace, Class playerClass) + SpellCastResult CheckCast() + { + Unit target = GetExplTargetUnit(); + if (target != null) { - CharBaseInfoRecord charBaseInfo = DB2Mgr.GetCharBaseInfo(nativeRace, playerClass); - if (charBaseInfo != null && ObjectMgr.GetPlayerInfo((Race)charBaseInfo.OtherFactionRaceID, playerClass) != null) + if (target.HasAura(SpellIds.RecentlyBandaged)) + return SpellCastResult.TargetAurastate; + } + return SpellCastResult.SpellCastOk; + } + + void HandleScript() + { + Unit target = GetHitUnit(); + if (target != null) + GetCaster().CastSpell(target, SpellIds.RecentlyBandaged, true); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + AfterHit.Add(new(HandleScript)); + } +} + +[Script] // 193970 - Mercenary Shapeshift +class spell_gen_battleground_mercenary_shapeshift : AuraScript +{ + static Dictionary RaceDisplayIds = new() + { + [Race.Human] = [55239, 55238], + [Race.Orc] = [55257, 55256], + [Race.Dwarf] = [55241, 55240], + [Race.NightElf] = [55243, 55242], + [Race.Undead] = [55259, 55258], + [Race.Tauren] = [55261, 55260], + [Race.Gnome] = [55245, 55244], + [Race.Troll] = [55263, 55262], + [Race.Goblin] = [55267, 57244], + [Race.BloodElf] = [55265, 55264], + [Race.Draenei] = [55247, 55246], + [Race.Worgen] = [55255, 55254], + [Race.PandarenNeutral] = [55253, 55252], // not verified, might be swapped with RacePandarenHorde + [Race.PandarenAlliance] = [55249, 55248], + [Race.PandarenHorde] = [55251, 55250], + [Race.Nightborne] = [82375, 82376], + [Race.HighmountainTauren] = [82377, 82378], + [Race.VoidElf] = [82371, 82372], + [Race.LightforgedDraenei] = [82373, 82374], + [Race.ZandalariTroll] = [88417, 88416], + [Race.KulTiran] = [88414, 88413], + [Race.DarkIronDwarf] = [88409, 88408], + [Race.Vulpera] = [94999, 95001], + [Race.MagharOrc] = [88420, 88410], + [Race.MechaGnome] = [94998, 95000] + }; + + List RacialSkills = new(); + + static Race GetReplacementRace(Race nativeRace, Class playerClass) + { + var charBaseInfo = Global.DB2Mgr.GetCharBaseInfo(nativeRace, playerClass); + if (charBaseInfo != null) + if (Global.ObjectMgr.GetPlayerInfo((Race)charBaseInfo.OtherFactionRaceID, playerClass) != null) return (Race)charBaseInfo.OtherFactionRaceID; - return Race.None; - } + return Race.None; + } - uint GetDisplayIdForRace(Race race, Gender gender) + static uint GetDisplayIdForRace(Race race, Gender gender) + { + var displayIds = RaceDisplayIds.LookupByKey(race); + if (displayIds != null) + return displayIds[(int)gender]; + + return 0; + } + + public override bool Validate(SpellInfo spellInfo) + { + foreach (var (race, displayIds) in RaceDisplayIds) { - var displayIds = RaceDisplayIds.LookupByKey(race); - if (!displayIds.Empty()) - return displayIds[(int)gender]; + if (!CliDB.ChrRacesStorage.ContainsKey((uint)race)) + return false; - return 0; - } - - public override bool Validate(SpellInfo spellInfo) - { - foreach (var (race, displayIds) in RaceDisplayIds) - { - if (!CliDB.ChrRacesStorage.ContainsKey(race)) + foreach (uint displayId in displayIds) + if (!CliDB.CreatureDisplayInfoStorage.ContainsKey(displayId)) return false; - - foreach (uint displayId in displayIds) - if (!CliDB.CreatureDisplayInfoStorage.ContainsKey(displayId)) - return false; - } - - RacialSkills.Clear(); - foreach (var skillLine in CliDB.SkillLineStorage.Values) - if (skillLine.HasFlag(SkillLineFlags.RacialForThePurposeOfTemporaryRaceChange)) - RacialSkills.Add(skillLine.Id); - - return true; } - void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) + RacialSkills.Clear(); + foreach (var (_, skillLine) in CliDB.SkillLineStorage) + if (skillLine.HasFlag(SkillLineFlags.RacialForThePurposeOfTemporaryRaceChange)) + RacialSkills.Add(skillLine.Id); + + return true; + } + + void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit owner = GetUnitOwner(); + Race otherFactionRace = GetReplacementRace(owner.GetRace(), owner.GetClass()); + if (otherFactionRace == Race.None) + return; + + uint displayId = GetDisplayIdForRace(otherFactionRace, owner.GetNativeGender()); + if (displayId != 0) + owner.SetDisplayId(displayId); + + if (mode.HasAnyFlag(AuraEffectHandleModes.Real)) + UpdateRacials(owner.GetRace(), otherFactionRace); + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit owner = GetUnitOwner(); + Race otherFactionRace = GetReplacementRace(owner.GetRace(), owner.GetClass()); + if (otherFactionRace == Race.None) + return; + + UpdateRacials(otherFactionRace, owner.GetRace()); + } + + void UpdateRacials(Race oldRace, Race newRace) + { + Player player = GetUnitOwner().ToPlayer(); + if (player == null) + return; + + foreach (uint racialSkillId in RacialSkills) { - Unit owner = GetUnitOwner(); - Race otherFactionRace = GetReplacementRace(owner.GetRace(), owner.GetClass()); - if (otherFactionRace == Race.None) + if (Global.DB2Mgr.GetSkillRaceClassInfo(racialSkillId, oldRace, player.GetClass()) != null) + { + var skillLineAbilities = Global.DB2Mgr.GetSkillLineAbilitiesBySkill(racialSkillId); + if (skillLineAbilities != null) + foreach (var ability in skillLineAbilities) + player.RemoveSpell(ability.Spell, false, false); + } + + if (Global.DB2Mgr.GetSkillRaceClassInfo(racialSkillId, newRace, player.GetClass()) != null) + player.LearnSkillRewardedSpells(racialSkillId, player.GetMaxSkillValueForLevel(), newRace); + } + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleApply, 0, AuraType.Transform, AuraEffectHandleModes.SendForClientMask)); + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Transform, AuraEffectHandleModes.Real)); + } +} + +[Script] // Blood Reserve - 64568 +class spell_gen_blood_reserve : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GenBloodReserveHeal); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + Unit caster = eventInfo.GetActionTarget(); + if (caster != null) + if (caster.HealthBelowPct(35)) + return true; + + return false; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActionTarget(); + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount()); + caster.CastSpell(caster, SpellIds.GenBloodReserveHeal, args); + caster.RemoveAura(SpellIds.GenBloodReserveAura); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] +class spell_gen_bonked : SpellScript +{ + void HandleScript(uint effIndex) + { + Player target = GetHitPlayer(); + if (target != null) + { + Aura aura = GetHitAura(); + if (!(aura != null && aura.GetStackAmount() == 3)) return; - uint displayId = GetDisplayIdForRace(otherFactionRace, owner.GetNativeGender()); - if (displayId != 0) - owner.SetDisplayId(displayId); + target.CastSpell(target, SpellIds.FoamSwordDefeat, true); + target.RemoveAurasDueToSpell(SpellIds.Bonked); - if (mode.HasFlag(AuraEffectHandleModes.Real)) - UpdateRacials(owner.GetRace(), otherFactionRace); - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit owner = GetUnitOwner(); - Race otherFactionRace = GetReplacementRace(owner.GetRace(), owner.GetClass()); - if (otherFactionRace == Race.None) - return; - - UpdateRacials(otherFactionRace, owner.GetRace()); - } - - void UpdateRacials(Race oldRace, Race newRace) - { - Player player = GetUnitOwner().ToPlayer(); - if (player == null) - return; - - foreach (uint racialSkillId in RacialSkills) + Aura auraOnGuard = target.GetAura(SpellIds.OnGuard); + if (auraOnGuard != null) { - if (DB2Mgr.GetSkillRaceClassInfo(racialSkillId, oldRace, player.GetClass()) != null) + Item item = target.GetItemByGuid(auraOnGuard.GetCastItemGUID()); + if (item != null) + target.DestroyItemCount(item.GetEntry(), 1, true); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); + } +} + +[Script("spell_gen_break_shield")] +[Script("spell_gen_tournament_counterattack")] +class spell_gen_break_shield : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(62552, 62719, 64100, 66482); + } + + void HandleScriptEffect(uint effIndex) + { + Unit target = GetHitUnit(); + + switch (effIndex) + { + case 0: // On spells wich trigger the damaging spell (and also the visual) + { + uint spellId; + + switch (GetSpellInfo().Id) { - var skillLineAbilities = DB2Mgr.GetSkillLineAbilitiesBySkill(racialSkillId); - if (skillLineAbilities != null) - foreach (var ability in skillLineAbilities) - player.RemoveSpell(ability.Spell, false, false); - } - - if (DB2Mgr.GetSkillRaceClassInfo(racialSkillId, newRace, player.GetClass()) != null) - player.LearnSkillRewardedSpells(racialSkillId, player.GetMaxSkillValueForLevel(), newRace); - } - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleApply, 0, AuraType.Transform, AuraEffectHandleModes.SendForClientMask)); - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Transform, AuraEffectHandleModes.Real)); - } - } - - [Script] // Blood Reserve - 64568 - class spell_gen_blood_reserve : AuraScript - { - const uint SpellGenBloodReserveAura = 64568; - const uint SpellGenBloodReserveHeal = 64569; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellGenBloodReserveHeal); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - Unit caster = eventInfo.GetActionTarget(); - if (caster != null) - if (caster.HealthBelowPct(35)) - return true; - - return false; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActionTarget(); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount()); - caster.CastSpell(caster, SpellGenBloodReserveHeal, args); - caster.RemoveAura(SpellGenBloodReserveAura); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] - class spell_gen_bonked : SpellScript - { - const uint SpellBonked = 62991; - const uint SpellFoamSwordDefeat = 62994; - const uint SpellOnGuard = 62972; - - void HandleScript(uint effIndex) - { - Player target = GetHitPlayer(); - if (target != null) - { - Aura aura = GetHitAura(); - if (!(aura != null && aura.GetStackAmount() == 3)) - return; - - target.CastSpell(target, SpellFoamSwordDefeat, true); - target.RemoveAurasDueToSpell(SpellBonked); - - Aura auraOnGuard = target.GetAura(SpellOnGuard); - if (auraOnGuard != null) - { - Item item = target.GetItemByGuid(auraOnGuard.GetCastItemGUID()); - if (item != null) - target.DestroyItemCount(item.GetEntry(), 1, true); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); - } - } - - [Script("spell_gen_break_shield")] - [Script("spell_gen_tournament_counterattack")] - class spell_gen_break_shield : SpellScript - { - const uint SpellBreakShieldDamage2K = 62626; - const uint SpellBreakShieldDamage10K = 64590; - - const uint SpellBreakShieldTriggerFactionMounts = 62575; // Also on ToC5 mounts - const uint SpellBreakShieldTriggerCampaingWarhorse = 64595; - const uint SpellBreakShieldTriggerUnk = 66480; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(62552, 62719, 64100, 66482); - } - - void HandleScriptEffect(uint effIndex) - { - Unit target = GetHitUnit(); - - switch (effIndex) - { - case 0: // On spells wich trigger the damaging spell (and also the visual) - { - uint spellId; - - switch (GetSpellInfo().Id) - { - case SpellBreakShieldTriggerUnk: - case SpellBreakShieldTriggerCampaingWarhorse: - spellId = SpellBreakShieldDamage10K; - break; - case SpellBreakShieldTriggerFactionMounts: - spellId = SpellBreakShieldDamage2K; - break; - default: - return; - } - - Unit rider = GetCaster().GetCharmer(); - if (rider != null) - rider.CastSpell(target, spellId, false); - else - GetCaster().CastSpell(target, spellId, false); - break; - } - case 1: // On damaging spells, for removing a defend layer - { - var auras = target.GetAppliedAuras(); - foreach (var pair in auras) - { - Aura aura = pair.Value.GetBase(); - if (aura != null) - { - if (aura.GetId() == 62552 || aura.GetId() == 62719 || aura.GetId() == 64100 || aura.GetId() == 66482) - { - aura.ModStackAmount(-1, AuraRemoveMode.EnemySpell); - // Remove dummys from rider (Necessary for updating visual shields) - Unit rider = target.GetCharmer(); - if (rider != null) - { - Aura defend = rider.GetAura(aura.GetId()); - if (defend != null) - defend.ModStackAmount(-1, AuraRemoveMode.EnemySpell); - } - break; - } - } - } - break; - } - default: - break; - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, SpellConst.EffectFirstFound, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 48750 - Burning Depths Necrolyte Image - class spell_gen_burning_depths_necrolyte_image : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 2)) && ValidateSpellInfo((uint)(spellInfo.GetEffect(2).CalcValue())); - } - - void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(GetTarget(), (uint)GetEffectInfo(2).CalcValue()); - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell((uint)GetEffectInfo(2).CalcValue(), GetCasterGUID()); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleApply, 0, AuraType.Transform, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Transform, AuraEffectHandleModes.Real)); - } - } - - [Script] - class spell_gen_cannibalize : SpellScript - { - const uint SpellCannibalizeTriggered = 20578; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellCannibalizeTriggered); - } - - SpellCastResult CheckIfCorpseNear() - { - Unit caster = GetCaster(); - float max_range = GetSpellInfo().GetMaxRange(false); - // search for nearby enemy corpse in range - AnyDeadUnitSpellTargetInRangeCheck check = new(caster, max_range, GetSpellInfo(), SpellTargetCheckTypes.Enemy, SpellTargetObjectTypes.CorpseEnemy); - WorldObjectSearcher searcher = new(caster, check); - Cell.VisitWorldObjects(caster, searcher, max_range); - if (searcher.GetResult() == null) - Cell.VisitGridObjects(caster, searcher, max_range); - if (searcher.GetResult() == null) - return SpellCastResult.NoEdibleCorpses; - return SpellCastResult.SpellCastOk; - } - - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), SpellCannibalizeTriggered, false); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - OnCheckCast.Add(new(CheckIfCorpseNear)); - } - } - - [Script] // 66020 Chains of Ice - class spell_gen_chains_of_ice : AuraScript - { - void UpdatePeriodic(AuraEffect aurEff) - { - // Get 0 effect aura - AuraEffect slow = GetAura().GetEffect(0); - if (slow == null) - return; - - int newAmount = Math.Min(slow.GetAmount() + aurEff.GetAmount(), 0); - slow.ChangeAmount(newAmount); - } - - public override void Register() - { - OnEffectUpdatePeriodic.Add(new(UpdatePeriodic, 1, AuraType.PeriodicDummy)); - } - } - - [Script] - class spell_gen_chaos_blast : SpellScript - { - const uint SpellChaosBlast = 37675; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellChaosBlast); - } - - void HandleDummy(uint effIndex) - { - int basepoints0 = 100; - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - if (target != null) - { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, basepoints0); - caster.CastSpell(target, SpellChaosBlast, args); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 28471 - ClearAll - class spell_clear_all : SpellScript - { - void HandleScript(uint effIndex) - { - Unit caster = GetCaster(); - caster.RemoveAllAurasOnDeath(); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_clone : SpellScript - { - const uint SpellNightmareFigmentMirrorImage = 57528; - - void HandleScriptEffect(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - GetHitUnit().CastSpell(GetCaster(), (uint)GetEffectValue(), true); - } - - public override void Register() - { - if (m_scriptSpellId == SpellNightmareFigmentMirrorImage) - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.Dummy)); - OnEffectHitTarget.Add(new(HandleScriptEffect, 2, SpellEffectName.Dummy)); - } - else - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); - OnEffectHitTarget.Add(new(HandleScriptEffect, 2, SpellEffectName.ScriptEffect)); - } - } - } - - [Script] - class spell_gen_clone_weapon : SpellScript - { - void HandleScriptEffect(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - GetHitUnit().CastSpell(GetCaster(), (uint)GetEffectValue(), true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_clone_weapon_AuraScript : AuraScript - { - const uint SpellCopyWeaponAura = 41054; - const uint SpellCopyWeapon2Aura = 63418; - const uint SpellCopyWeapon3Aura = 69893; - - const uint SpellCopyOffhandAura = 45205; - const uint SpellCopyOffhand2Aura = 69896; - - const uint SpellCopyRangedAura = 57594; - - uint prevItem; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellCopyWeaponAura, SpellCopyWeapon2Aura, SpellCopyWeapon3Aura, SpellCopyOffhandAura, SpellCopyOffhand2Aura, SpellCopyRangedAura); - } - - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - Unit target = GetTarget(); - if (caster == null) - return; - - switch (GetSpellInfo().Id) - { - case SpellCopyWeaponAura: - case SpellCopyWeapon2Aura: - case SpellCopyWeapon3Aura: - { - prevItem = target.GetVirtualItemId(0); - - Player player = caster.ToPlayer(); - if (player != null) - { - Item mainItem = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.MainHand); - if (mainItem != null) - target.SetVirtualItem(0, mainItem.GetEntry()); - } - else - target.SetVirtualItem(0, caster.GetVirtualItemId(0)); - break; - } - case SpellCopyOffhandAura: - case SpellCopyOffhand2Aura: - { - prevItem = target.GetVirtualItemId(1); - - Player player = caster.ToPlayer(); - if (player != null) - { - Item offItem = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.OffHand); - if (offItem != null) - target.SetVirtualItem(1, offItem.GetEntry()); - } - else - target.SetVirtualItem(1, caster.GetVirtualItemId(1)); - break; - } - case SpellCopyRangedAura: - { - prevItem = target.GetVirtualItemId(2); - - Player player = caster.ToPlayer(); - if (player != null) - { - Item rangedItem = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.MainHand); - if (rangedItem != null) - target.SetVirtualItem(2, rangedItem.GetEntry()); - } - else - target.SetVirtualItem(2, caster.GetVirtualItemId(2)); - break; - } - default: - break; - } - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - - switch (GetSpellInfo().Id) - { - case SpellCopyWeaponAura: - case SpellCopyWeapon2Aura: - case SpellCopyWeapon3Aura: - target.SetVirtualItem(0, prevItem); - break; - case SpellCopyOffhandAura: - case SpellCopyOffhand2Aura: - target.SetVirtualItem(1, prevItem); - break; - case SpellCopyRangedAura: - target.SetVirtualItem(2, prevItem); - break; - default: - break; - } - } - - public override void Register() - { - OnEffectApply.Add(new(OnApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); - OnEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); - } - } - - [Script("spell_gen_default_count_pct_from_max_hp", 0)] - [Script("spell_gen_50pct_count_pct_from_max_hp", 50)] - class spell_gen_count_pct_from_max_hp : SpellScript - { - int _damagePct; - - public spell_gen_count_pct_from_max_hp(int damagePct) - { - _damagePct = damagePct; - } - - void RecalculateDamage() - { - if (_damagePct == 0) - _damagePct = GetHitDamage(); - - SetHitDamage((int)GetHitUnit().CountPctFromMaxHealth(_damagePct)); - } - - public override void Register() - { - OnHit.Add(new(RecalculateDamage)); - } - } - - // 28865 - Consumption - [Script] // 64208 - Consumption - class spell_gen_consumption : SpellScript - { - void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - SpellInfo createdBySpell = SpellMgr.GetSpellInfo(GetCaster().m_unitData.CreatedBySpell, GetCastDifficulty()); - if (createdBySpell != null) - damage = createdBySpell.GetEffect(1).CalcValue(); - } - - public override void Register() - { - CalcDamage.Add(new(CalculateDamage)); - } - } - - [Script] // 63845 - Create Lance - class spell_gen_create_lance : SpellScript - { - const uint SpellCreateLanceAlliance = 63914; - const uint SpellCreateLanceHorde = 63919; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellCreateLanceAlliance, SpellCreateLanceHorde); - } - - void HandleScript(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - - Player target = GetHitPlayer(); - if (target != null) - { - if (target.GetTeam() == Team.Alliance) - GetCaster().CastSpell(target, SpellCreateLanceAlliance, true); - else if (target.GetTeam() == Team.Horde) - GetCaster().CastSpell(target, SpellCreateLanceHorde, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script("spell_gen_sunreaver_disguise")] - [Script("spell_gen_silver_covenant_disguise")] - class spell_gen_dalaran_disguise : SpellScript - { - const uint SpellSunreaverDisguiseTrigger = 69672; - const uint SpellSunreaverDisguiseFemale = 70973; - const uint SpellSunreaverDisguiseMale = 70974; - - const uint SpellSilverCovenantDisguiseTrigger = 69673; - const uint SpellSilverCovenantDisguiseFemale = 70971; - const uint SpellSilverCovenantDisguiseMale = 70972; - - public override bool Validate(SpellInfo spellInfo) - { - switch (spellInfo.Id) - { - case SpellSunreaverDisguiseTrigger: - return ValidateSpellInfo(SpellSunreaverDisguiseFemale, SpellSunreaverDisguiseMale); - case SpellSilverCovenantDisguiseTrigger: - return ValidateSpellInfo(SpellSilverCovenantDisguiseFemale, SpellSilverCovenantDisguiseMale); - default: - break; - } - - return false; - } - - void HandleScript(uint effIndex) - { - Player player = GetHitPlayer(); - if (player != null) - { - Gender gender = player.GetNativeGender(); - - uint spellId = GetSpellInfo().Id; - - switch (spellId) - { - case SpellSunreaverDisguiseTrigger: - spellId = gender == Gender.Female ? SpellSunreaverDisguiseFemale : SpellSunreaverDisguiseMale; + case SpellIds.BreakShieldTriggerUnk: + case SpellIds.BreakShieldTriggerCampaingWarhorse: + spellId = SpellIds.BreakShieldDamage10K; break; - case SpellSilverCovenantDisguiseTrigger: - spellId = gender == Gender.Female ? SpellSilverCovenantDisguiseFemale : SpellSilverCovenantDisguiseMale; + case SpellIds.BreakShieldTriggerFactionMounts: + spellId = SpellIds.BreakShieldDamage2K; break; default: - break; + return; } - GetCaster().CastSpell(player, spellId, true); + Unit rider = GetCaster().GetCharmer(); + if (rider != null) + rider.CastSpell(target, spellId, false); + else + GetCaster().CastSpell(target, spellId, false); + break; } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_decay_over_time_spell : SpellScript - { - void ModAuraStack() - { - Aura aur = GetHitAura(); - if (aur != null) - aur.SetStackAmount((byte)GetSpellInfo().StackAmount); - } - - public override void Register() - { - AfterHit.Add(new(ModAuraStack)); - } - } - - [Script] // 32065 - Fungal Decay - class spell_gen_decay_over_time_fungal_decay : AuraScript - { - // found in sniffs, there is no duration entry we can possibly use - const int AuraDuration = 12600; - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetSpellInfo() == GetSpellInfo(); - } - - void Decay(ProcEventInfo eventInfo) - { - PreventDefaultAction(); - ModStackAmount(-1); - } - - void ModDuration(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // only on actual reapply, not on stack decay - if (GetDuration() == GetMaxDuration()) + case 1: // On damaging spells, for removing a defend layer { - SetMaxDuration(AuraDuration); - SetDuration(AuraDuration); - } - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnProc.Add(new(Decay)); - OnEffectApply.Add(new(ModDuration, 0, AuraType.ModDecreaseSpeed, AuraEffectHandleModes.RealOrReapplyMask)); - } - } - - // 36659 - Tail Sting - [Script] // 36659 - Tail Sting - class spell_gen_decay_over_time_tail_sting : AuraScript - { - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetSpellInfo() == GetSpellInfo(); - } - - void Decay(ProcEventInfo eventInfo) - { - PreventDefaultAction(); - ModStackAmount(-1); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnProc.Add(new(Decay)); - } - } - - [Script] - class spell_gen_defend : AuraScript - { - const uint SpellVisualShield1 = 63130; - const uint SpellVisualShield2 = 63131; - const uint SpellVisualShield3 = 63132; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellVisualShield1, SpellVisualShield2, SpellVisualShield3); - } - - void RefreshVisualShields(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetCaster() != null) - { - Unit target = GetTarget(); - - for (byte i = 0; i < GetSpellInfo().StackAmount; ++i) - target.RemoveAurasDueToSpell(SpellVisualShield1 + i); - - target.CastSpell(target, SpellVisualShield1 + GetAura().GetStackAmount() - 1, aurEff); - } - else - GetTarget().RemoveAurasDueToSpell(GetId()); - } - - void RemoveVisualShields(AuraEffect aurEff, AuraEffectHandleModes mode) - { - for (byte i = 0; i < GetSpellInfo().StackAmount; ++i) - GetTarget().RemoveAurasDueToSpell(SpellVisualShield1 + i); - } - - void RemoveDummyFromDriver(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - { - TempSummon vehicle = caster.ToTempSummon(); - if (vehicle != null) + var auras = target.GetAppliedAuras(); + foreach (var itr in auras) { - Unit rider = vehicle.GetSummonerUnit(); - if (rider != null) - rider.RemoveAurasDueToSpell(GetId()); + Aura aura = itr.Value.GetBase(); + if (aura != null) + { + if (aura.GetId() == 62552 || aura.GetId() == 62719 || aura.GetId() == 64100 || aura.GetId() == 66482) + { + aura.ModStackAmount(-1, AuraRemoveMode.EnemySpell); + // Remove dummys from rider (Necessary for updating visual shields) + Unit rider = target.GetCharmer(); + if (rider != null) + { + Aura defend = rider.GetAura(aura.GetId()); + if (defend != null) + defend.ModStackAmount(-1, AuraRemoveMode.EnemySpell); + } + break; + } + } } + break; } - } - - public override void Register() - { - /*SpellInfo spell = SpellMgr.GetSpellInfo(m_scriptSpellId, Difficulty.None); - - // 6.x effects Removed - - // Defend spells cast by NPCs (add visuals) - if (spell.GetEffect(0).ApplyAuraName == AuraType.ModDamagePercentTaken) - { - AfterEffectApply.Add(new(RefreshVisualShields, 0, AuraType.ModDamagePercentTaken, AuraEffectHandleModes.RealOrReapplyMask)); - OnEffectRemove.Add(new(RemoveVisualShields, 0, AuraType.ModDamagePercentTaken, AuraEffectHandleModes.ChangeAmountMask)); - } - - // Remove Defend spell from player when he dismounts - if (spell.GetEffect(2).ApplyAuraName == AuraType.ModDamagePercentTaken) - OnEffectRemove.Add(new(RemoveDummyFromDriver, 2, AuraType.ModDamagePercentTaken, AuraEffectHandleModes.Real)); - - // Defend spells cast by players (add/Remove visuals) - if (spell.GetEffect(1).ApplyAuraName == AuraType.Dummy) - { - AfterEffectApply.Add(new(RefreshVisualShields, 1, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); - OnEffectRemove.Add(new(RemoveVisualShields, 1, AuraType.Dummy, AuraEffectHandleModes.ChangeAmountMask)); - }*/ + default: + break; } } - [Script] - class spell_gen_despawn_AuraScript : AuraScript + public override void Register() { - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + OnEffectHitTarget.Add(new(HandleScriptEffect, SpellConst.EffectFirstFound, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 48750 - Burning Depths Necrolyte Image +class spell_gen_burning_depths_necrolyte_image : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 2)) + && ValidateSpellInfo((uint)spellInfo.GetEffect(2).CalcValue()); + } + + void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), (uint)GetEffectInfo(2).CalcValue()); + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell((uint)GetEffectInfo(2).CalcValue(), GetCasterGUID()); + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleApply, 0, AuraType.Transform, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Transform, AuraEffectHandleModes.Real)); + } +} + +[Script] +class spell_gen_cannibalize : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CannibalizeTriggered); + } + + SpellCastResult CheckIfCorpseNear() + { + Unit caster = GetCaster(); + float max_range = GetSpellInfo().GetMaxRange(false); + // search for nearby enemy corpse in range + AnyDeadUnitSpellTargetInRangeCheck check = new(caster, max_range, GetSpellInfo(), SpellTargetCheckTypes.Enemy, SpellTargetObjectTypes.CorpseEnemy); + WorldObjectSearcher searcher = new(caster, check); + Cell.VisitWorldObjects(caster, searcher, max_range); + if (searcher.GetResult() == null) + Cell.VisitGridObjects(caster, searcher, max_range); + if (searcher.HasResult()) + return SpellCastResult.NoEdibleCorpses; + return SpellCastResult.SpellCastOk; + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.CannibalizeTriggered, false); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + OnCheckCast.Add(new(CheckIfCorpseNear)); + } +} + +[Script] // 66020 Chains of Ice +class spell_gen_chains_of_ice : AuraScript +{ + void UpdatePeriodic(AuraEffect aurEff) + { + // Get 0 effect aura + AuraEffect slow = GetAura().GetEffect(0); + if (slow == null) + return; + + int newAmount = Math.Min(slow.GetAmount() + aurEff.GetAmount(), 0); + slow.ChangeAmount(newAmount); + } + + public override void Register() + { + OnEffectUpdatePeriodic.Add(new(UpdatePeriodic, 1, AuraType.PeriodicDummy)); + } +} + +[Script] +class spell_gen_chaos_blast : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChaosBlast); + } + + void HandleDummy(uint effIndex) + { + int basepoints0 = 100; + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target != null) { - Creature target = GetTarget().ToCreature(); + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.AddSpellMod(SpellValueMod.BasePoint0, basepoints0); + caster.CastSpell(target, SpellIds.ChaosBlast, args); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 28471 - ClearAll +class spell_clear_all : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit caster = GetCaster(); + caster.RemoveAllAurasOnDeath(); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_clone : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit().CastSpell(GetCaster(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + if (m_scriptSpellId == SpellIds.NightmareFigmentMirrorImage) + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.Dummy)); + OnEffectHitTarget.Add(new(HandleScriptEffect, 2, SpellEffectName.Dummy)); + } + else + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); + OnEffectHitTarget.Add(new(HandleScriptEffect, 2, SpellEffectName.ScriptEffect)); + } + } +} + +[Script] +class spell_gen_clone_weapon : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit().CastSpell(GetCaster(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_clone_weapon_aura : AuraScript +{ + uint prevItem = 0; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CopyWeaponAura, SpellIds.CopyWeapon2Aura, SpellIds.CopyWeapon3Aura, SpellIds.CopyOffhandAura, SpellIds.CopyOffhand2Aura, SpellIds.CopyRangedAura); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + Unit target = GetTarget(); + if (caster == null) + return; + + switch (GetSpellInfo().Id) + { + case SpellIds.CopyWeaponAura: + case SpellIds.CopyWeapon2Aura: + case SpellIds.CopyWeapon3Aura: + { + prevItem = target.GetVirtualItemId(0); + + Player player = caster.ToPlayer(); + if (player != null) + { + Item mainItem = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.MainHand); + if (mainItem != null) + target.SetVirtualItem(0, mainItem.GetEntry()); + } + else + target.SetVirtualItem(0, caster.GetVirtualItemId(0)); + break; + } + case SpellIds.CopyOffhandAura: + case SpellIds.CopyOffhand2Aura: + { + prevItem = target.GetVirtualItemId(1); + + Player player = caster.ToPlayer(); + if (player != null) + { + Item offItem = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.OffHand); + if (offItem != null) + target.SetVirtualItem(1, offItem.GetEntry()); + } + else + target.SetVirtualItem(1, caster.GetVirtualItemId(1)); + break; + } + case SpellIds.CopyRangedAura: + { + prevItem = target.GetVirtualItemId(2); + + Player player = caster.ToPlayer(); + if (player != null) + { + Item rangedItem = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.MainHand); + if (rangedItem != null) + target.SetVirtualItem(2, rangedItem.GetEntry()); + } + else + target.SetVirtualItem(2, caster.GetVirtualItemId(2)); + break; + } + default: + break; + } + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + + switch (GetSpellInfo().Id) + { + case SpellIds.CopyWeaponAura: + case SpellIds.CopyWeapon2Aura: + case SpellIds.CopyWeapon3Aura: + target.SetVirtualItem(0, prevItem); + break; + case SpellIds.CopyOffhandAura: + case SpellIds.CopyOffhand2Aura: + target.SetVirtualItem(1, prevItem); + break; + case SpellIds.CopyRangedAura: + target.SetVirtualItem(2, prevItem); + break; + default: + break; + } + } + + public override void Register() + { + OnEffectApply.Add(new(OnApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); + OnEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +[Script("spell_gen_default_count_pct_from_max_hp", 0)] +[Script("spell_gen_50pct_count_pct_from_max_hp", 50)] +class spell_gen_count_pct_from_max_hp(int damagePct) : SpellScript() +{ + void RecalculateDamage() + { + if (damagePct == 0) + damagePct = GetHitDamage(); + + SetHitDamage((int)GetHitUnit().CountPctFromMaxHealth(damagePct)); + } + + public override void Register() + { + OnHit.Add(new(RecalculateDamage)); + } +} + +// 28865 - Consumption +[Script] // 64208 - Consumption +class spell_gen_consumption : SpellScript +{ + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + SpellInfo createdBySpell = Global.SpellMgr.GetSpellInfo(GetCaster().m_unitData.CreatedBySpell, GetCastDifficulty()); + if (createdBySpell != null) + damage = createdBySpell.GetEffect(1).CalcValue(); + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamage)); + } +} + +[Script] // 63845 - Create Lance +class spell_gen_create_lance : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CreateLanceAlliance, SpellIds.CreateLanceHorde); + } + + void HandleScript(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + + Player target = GetHitPlayer(); + if (target != null) + { + if (target.GetTeam() == Team.Alliance) + GetCaster().CastSpell(target, SpellIds.CreateLanceAlliance, true); + else if (target.GetTeam() == Team.Horde) + GetCaster().CastSpell(target, SpellIds.CreateLanceHorde, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script("spell_gen_sunreaver_disguise")] +[Script("spell_gen_silver_covenant_disguise")] +class spell_gen_dalaran_disguise : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + switch (spellInfo.Id) + { + case SpellIds.SunreaverDisguiseTrigger: + return ValidateSpellInfo(SpellIds.SunreaverDisguiseFemale, SpellIds.SunreaverDisguiseMale); + case SpellIds.SilverCovenantDisguiseTrigger: + return ValidateSpellInfo(SpellIds.SilverCovenantDisguiseFemale, SpellIds.SilverCovenantDisguiseMale); + default: + break; + } + + return false; + } + + void HandleScript(uint effIndex) + { + Player player = GetHitPlayer(); + if (player != null) + { + Gender gender = player.GetNativeGender(); + + uint spellId = GetSpellInfo().Id; + switch (spellId) + { + case SpellIds.SunreaverDisguiseTrigger: + spellId = gender == Gender.Female ? SpellIds.SunreaverDisguiseFemale : SpellIds.SunreaverDisguiseMale; + break; + case SpellIds.SilverCovenantDisguiseTrigger: + spellId = gender == Gender.Female ? SpellIds.SilverCovenantDisguiseFemale : SpellIds.SilverCovenantDisguiseMale; + break; + default: + break; + } + + GetCaster().CastSpell(player, spellId, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_decay_over_time_spell : SpellScript +{ + void ModAuraStack() + { + Aura aur = GetHitAura(); + if (aur != null) + aur.SetStackAmount((byte)GetSpellInfo().StackAmount); + } + + public override void Register() + { + AfterHit.Add(new(ModAuraStack)); + } +} + +[Script] // 32065 - Fungal Decay +class spell_gen_decay_over_time_fungal_decay : AuraScript +{ + // found in sniffs, there is no duration entry we can possibly use + const int AuraDuration = 12600; + + bool CheckProc(ProcEventInfo eventInfo) + { + return (eventInfo.GetSpellInfo() == GetSpellInfo()); + } + + void Decay(ProcEventInfo eventInfo) + { + PreventDefaultAction(); + ModStackAmount(-1); + } + + void ModDuration(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // only on actual reapply, not on stack decay + if (GetDuration() == GetMaxDuration()) + { + SetMaxDuration(AuraDuration); + SetDuration(AuraDuration); + } + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnProc.Add(new(Decay)); + OnEffectApply.Add(new(ModDuration, 0, AuraType.ModDecreaseSpeed, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +[Script] // 36659 - Tail Sting +class spell_gen_decay_over_time_tail_sting : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) + { + return (eventInfo.GetSpellInfo() == GetSpellInfo()); + } + + void Decay(ProcEventInfo eventInfo) + { + PreventDefaultAction(); + ModStackAmount(-1); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnProc.Add(new(Decay)); + } +} + +[Script] +class spell_gen_defend : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VisualShield1, SpellIds.VisualShield2, SpellIds.VisualShield3); + } + + void RefreshVisualShields(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetCaster() != null) + { + Unit target = GetTarget(); + + for (byte i = 0; i < GetSpellInfo().StackAmount; ++i) + target.RemoveAurasDueToSpell(SpellIds.VisualShield1 + i); + + target.CastSpell(target, SpellIds.VisualShield1 + GetAura().GetStackAmount() - 1, aurEff); + } + else + GetTarget().RemoveAurasDueToSpell(GetId()); + } + + void RemoveVisualShields(AuraEffect aurEff, AuraEffectHandleModes mode) + { + for (byte i = 0; i < GetSpellInfo().StackAmount; ++i) + GetTarget().RemoveAurasDueToSpell(SpellIds.VisualShield1 + i); + } + + void RemoveDummyFromDriver(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + { + TempSummon vehicle = caster.ToTempSummon(); + if (vehicle != null) + { + Unit rider = vehicle.GetSummonerUnit(); + if (rider != null) + rider.RemoveAurasDueToSpell(GetId()); + } + } + } + + public override void Register() + { + /* + SpellInfo spell = Global.SpellMgr.AssertSpellInfo(m_scriptSpellId, Difficulty.None); + + // 6.x effects removed + + // Defend spells cast by NPCs (add visuals) + if (spell.GetEffect(0).ApplyAuraName == SpellAuraModDamagePercentTaken) + { + AfterEffectApply.Add(new (RefreshVisualShields, 0, AuraType.ModDamagePercentTaken, AuraEffectHandleModes.RealOrReapplyMask)); + OnEffectRemove.Add(new (RemoveVisualShields, 0, AuraType.ModDamagePercentTaken, AuraEffectHandleModes.ChangeAmountMask)); + } + + // Remove Defend spell from player when he dismounts + if (spell.GetEffect(2).ApplyAuraName == SpellAuraModDamagePercentTaken) + OnEffectRemove.Add(new (RemoveDummyFromDriver, 2, AuraType.ModDamagePercentTaken, AuraEffectHandleModes.Real)); + + // Defend spells cast by players (add/remove visuals) + if (spell.GetEffect(1).ApplyAuraName == SpellAuraDummy) + { + AfterEffectApply.Add(new (RefreshVisualShields, 1, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); + OnEffectRemove.Add(new (RemoveVisualShields, 1, AuraType.Dummy, AuraEffectHandleModes.ChangeAmountMask)); + } + */ + } +} + +[Script] +class spell_gen_despawn_aura : AuraScript +{ + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Creature target = GetTarget().ToCreature(); + if (target != null) + target.DespawnOrUnsummon(); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, SpellConst.EffectFirstFound, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] /// @todo: migrate spells to spell_gen_despawn_target, then remove this +class spell_gen_despawn_self : SpellScript +{ + public override bool Load() + { + return GetCaster().IsUnit(); + } + + void HandleDummy(uint effIndex) + { + if (GetEffectInfo().IsEffect(SpellEffectName.Dummy) || GetEffectInfo().IsEffect(SpellEffectName.ScriptEffect)) + GetCaster().ToCreature().DespawnOrUnsummon(); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, SpellConst.EffectAll, SpellEffectName.Any)); + } +} + +[Script] +class spell_gen_despawn_target : SpellScript +{ + void HandleDespawn(uint effIndex) + { + if (GetEffectInfo().IsEffect(SpellEffectName.Dummy) || GetEffectInfo().IsEffect(SpellEffectName.ScriptEffect)) + { + Creature target = GetHitCreature(); if (target != null) target.DespawnOrUnsummon(); } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, SpellConst.EffectFirstFound, AuraType.Dummy, AuraEffectHandleModes.Real)); - } } - [Script] /// @todo: migrate spells to spell_gen_despawn_target, then Remove this - class spell_gen_despawn_self : SpellScript + public override void Register() { - public override bool Load() - { - return GetCaster().GetTypeId() == TypeId.Unit; - } + OnEffectHitTarget.Add(new(HandleDespawn, SpellConst.EffectAll, SpellEffectName.Any)); + } +} - void HandleDummy(uint effIndex) - { - if (GetEffectInfo().IsEffect(SpellEffectName.Dummy) || GetEffectInfo().IsEffect(SpellEffectName.ScriptEffect)) - GetCaster().ToCreature().DespawnOrUnsummon(); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, SpellConst.EffectAll, SpellEffectName.Any)); - } +[Script] // 70769 Divine Storm! +class spell_gen_divine_storm_cd_reset : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); } - [Script] - class spell_gen_despawn_target : SpellScript + public override bool Validate(SpellInfo spellInfo) { - void HandleDespawn(uint effIndex) - { - if (GetEffectInfo().IsEffect(SpellEffectName.Dummy) || GetEffectInfo().IsEffect(SpellEffectName.ScriptEffect)) - { - Creature target = GetHitCreature(); - if (target != null) - target.DespawnOrUnsummon(); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDespawn, SpellConst.EffectAll, SpellEffectName.Any)); - } + return ValidateSpellInfo(SpellIds.DivineStorm); } - [Script] // 70769 Divine Storm! - class spell_gen_divine_storm_cd_reset : SpellScript + void HandleScript(uint effIndex) { - const uint SpellDivineStorm = 53385; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDivineStorm); - } - - void HandleScript(uint effIndex) - { - GetCaster().GetSpellHistory().ResetCooldown(SpellDivineStorm, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.Dummy)); - } + GetCaster().GetSpellHistory().ResetCooldown(SpellIds.DivineStorm, true); } - [Script] - class spell_gen_ds_flush_knockback : SpellScript + public override void Register() { - void HandleScript(uint effIndex) - { - // Here the target is the water spout and determines the position where the player is knocked from - Unit target = GetHitUnit(); - if (target != null) - { - Player player = GetCaster().ToPlayer(); - if (player != null) - { - float horizontalSpeed = 20.0f + (40.0f - GetCaster().GetDistance(target)); - float verticalSpeed = 8.0f; - // This method relies on the Dalaran Sewer map disposition and Water Spout position - // What we do is knock the player from a position exactly behind him and at the end of the pipe - player.KnockbackFrom(target.GetPosition(), horizontalSpeed, verticalSpeed); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.Dummy)); - } + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.Dummy)); } +} - [Script] // 50051 - Ethereal Pet Aura - class spell_ethereal_pet_AuraScript : AuraScript +[Script] +class spell_gen_ds_flush_knockback : SpellScript +{ + void HandleScript(uint effIndex) { - const uint NpcEtherealSoulTrader = 27914; - - const uint SayStealEssence = 1; - - const uint SpellStealEssenceVisual = 50101; - - bool CheckProc(ProcEventInfo eventInfo) - { - uint levelDiff = (uint)Math.Abs(GetTarget().GetLevel() - eventInfo.GetProcTarget().GetLevel()); - return levelDiff <= 9; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - List minionList = new(); - GetUnitOwner().GetAllMinionsByEntry(minionList, NpcEtherealSoulTrader); - foreach (Creature minion in minionList) - { - if (minion.IsAIEnabled()) - { - minion.GetAI().Talk(SayStealEssence); - minion.CastSpell(eventInfo.GetProcTarget(), SpellStealEssenceVisual); - } - } - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 50052 - Ethereal Pet onSummon - class spell_ethereal_pet_onsummon : SpellScript - { - const uint SpellProcTriggerOnKillAura = 50051; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellProcTriggerOnKillAura); - } - - void HandleScriptEffect(uint effIndex) - { - Unit target = GetHitUnit(); - target.CastSpell(target, SpellProcTriggerOnKillAura, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 50055 - Ethereal Pet Aura Remove - class spell_ethereal_pet_aura_Remove : SpellScript - { - const uint SpellEtherealPetAura = 50055; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellEtherealPetAura); - } - - void HandleScriptEffect(uint effIndex) - { - GetHitUnit().RemoveAurasDueToSpell(SpellEtherealPetAura); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 50101 - Ethereal Pet OnKill Steal Essence - class spell_steal_essence_visual : AuraScript - { - const uint SpellCreateToken = 50063; - const uint SayCreateToken = 2; - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - { - caster.CastSpell(caster, SpellCreateToken, true); - Creature soulTrader = caster.ToCreature(); - if (soulTrader != null) - soulTrader.GetAI().Talk(SayCreateToken); - } - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - struct FeastSpellIds - { - public const uint GreatFeast = 57337; - public const uint FishFeast = 57397; - public const uint GiganticFeast = 58466; - public const uint SmallFeast = 58475; - public const uint BountifulFeast = 66477; - - public const uint FeastFood = 45548; - public const uint FeastDrink = 57073; - public const uint BountifulFeastDrink = 66041; - public const uint BountifulFeastFood = 66478; - - public const uint GreatFeastRefreshment = 57338; - public const uint FishFeastRefreshment = 57398; - public const uint GiganticFeastRefreshment = 58467; - public const uint SmallFeastRefreshment = 58477; - public const uint BountifulFeastRefreshment = 66622; - } - - //57397 - Fish Feast - //58466 - Gigantic Feast - //58475 - Small Feast - [Script] //66477 - Bountiful Feast - class spell_gen_feast : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(FeastSpellIds.FeastFood, FeastSpellIds.FeastDrink, FeastSpellIds.BountifulFeastDrink, FeastSpellIds.BountifulFeastFood, FeastSpellIds.GreatFeastRefreshment, FeastSpellIds.FishFeastRefreshment, - FeastSpellIds.GiganticFeastRefreshment, FeastSpellIds.SmallFeastRefreshment, FeastSpellIds.BountifulFeastRefreshment); - } - - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - - switch (GetSpellInfo().Id) - { - case FeastSpellIds.GreatFeast: - target.CastSpell(target, FeastSpellIds.FeastFood); - target.CastSpell(target, FeastSpellIds.FeastDrink); - target.CastSpell(target, FeastSpellIds.GreatFeastRefreshment); - break; - case FeastSpellIds.FishFeast: - target.CastSpell(target, FeastSpellIds.FeastFood); - target.CastSpell(target, FeastSpellIds.FeastDrink); - target.CastSpell(target, FeastSpellIds.FishFeastRefreshment); - break; - case FeastSpellIds.GiganticFeast: - target.CastSpell(target, FeastSpellIds.FeastFood); - target.CastSpell(target, FeastSpellIds.FeastDrink); - target.CastSpell(target, FeastSpellIds.GiganticFeastRefreshment); - break; - case FeastSpellIds.SmallFeast: - target.CastSpell(target, FeastSpellIds.FeastFood); - target.CastSpell(target, FeastSpellIds.FeastDrink); - target.CastSpell(target, FeastSpellIds.SmallFeastRefreshment); - break; - case FeastSpellIds.BountifulFeast: - target.CastSpell(target, FeastSpellIds.BountifulFeastRefreshment); - target.CastSpell(target, FeastSpellIds.BountifulFeastDrink); - target.CastSpell(target, FeastSpellIds.BountifulFeastFood); - break; - default: - break; - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_feign_death_all_flags : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetUnitFlag3(UnitFlags3.FakeDead); - target.SetUnitFlag2(UnitFlags2.FeignDeath); - target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.SetReactState(ReactStates.Passive); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveUnitFlag3(UnitFlags3.FakeDead); - target.RemoveUnitFlag2(UnitFlags2.FeignDeath); - target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.InitializeReactState(); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] - class spell_gen_feign_death_all_flags_uninteractible : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetUnitFlag3(UnitFlags3.FakeDead); - target.SetUnitFlag2(UnitFlags2.FeignDeath); - target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); - target.SetImmuneToAll(true); - target.SetUninteractible(true); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.SetReactState(ReactStates.Passive); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveUnitFlag3(UnitFlags3.FakeDead); - target.RemoveUnitFlag2(UnitFlags2.FeignDeath); - target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); - target.SetImmuneToAll(false); - target.SetUninteractible(false); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.InitializeReactState(); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 96733 - Permanent Feign Death (Stun) - class spell_gen_feign_death_all_flags_no_uninteractible : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetUnitFlag3(UnitFlags3.FakeDead); - target.SetUnitFlag2(UnitFlags2.FeignDeath); - target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); - target.SetImmuneToAll(true); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.SetReactState(ReactStates.Passive); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveUnitFlag3(UnitFlags3.FakeDead); - target.RemoveUnitFlag2(UnitFlags2.FeignDeath); - target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); - target.SetImmuneToAll(false); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.InitializeReactState(); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - // 35357 - Spawn Feign Death - [Script] // 51329 - Feign Death - class spell_gen_feign_death_no_dyn_flag : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetUnitFlag2(UnitFlags2.FeignDeath); - target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.SetReactState(ReactStates.Passive); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveUnitFlag2(UnitFlags2.FeignDeath); - target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.InitializeReactState(); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 58951 - Permanent Feign Death - class spell_gen_feign_death_no_prevent_emotes : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetUnitFlag3(UnitFlags3.FakeDead); - target.SetUnitFlag2(UnitFlags2.FeignDeath); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.SetReactState(ReactStates.Passive); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveUnitFlag3(UnitFlags3.FakeDead); - target.RemoveUnitFlag2(UnitFlags2.FeignDeath); - - Creature creature = target.ToCreature(); - if (creature != null) - creature.InitializeReactState(); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 35491 - Furious Rage - class spell_gen_furious_rage : AuraScript - { - const uint EmoteFuriousRage = 19415; - const uint EmoteExhausted = 18368; - const uint SpellExhaustion = 35492; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellExhaustion) && - CliDB.BroadcastTextStorage.HasRecord(EmoteFuriousRage) && - CliDB.BroadcastTextStorage.HasRecord(EmoteExhausted); - } - - void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.TextEmote(EmoteFuriousRage, target, false); - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; - - Unit target = GetTarget(); - target.TextEmote(EmoteExhausted, target, false); - target.CastSpell(target, SpellExhaustion, true); - } - - public override void Register() - { - AfterEffectApply.Add(new(AfterApply, 0, AuraType.ModDamagePercentDone, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.ModDamagePercentDone, AuraEffectHandleModes.Real)); - } - } - - [Script] // 46642 - 5,000 Gold - class spell_gen_5000_gold : SpellScript - { - void HandleScript(uint effIndex) - { - Player target = GetHitPlayer(); - if (target != null) - target.ModifyMoney(5000 * MoneyConstants.Gold); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 131474 - Fishing - class spell_gen_fishing : SpellScript - { - const uint SpellFishingNoFishingPole = 131476; - const uint SpellFishingWithPole = 131490; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFishingNoFishingPole, SpellFishingWithPole); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - uint spellId; - Item mainHand = GetCaster().ToPlayer().GetItemByPos(InventorySlots.Bag0, EquipmentSlot.MainHand); - if (mainHand == null || mainHand.GetTemplate().GetClass() != ItemClass.Weapon || mainHand.GetTemplate().GetSubClass() != (uint)ItemSubClassWeapon.FishingPole) - spellId = SpellFishingNoFishingPole; - else - spellId = SpellFishingWithPole; - - GetCaster().CastSpell(GetCaster(), spellId, false); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_gen_gadgetzan_transporter_backfire : SpellScript - { - const uint SpellTransporterMalfunctionPolymorph = 23444; - const uint SpellTransporterEvilTwin = 23445; - const uint SpellTransporterMalfunctionMiss = 36902; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellTransporterMalfunctionPolymorph, SpellTransporterEvilTwin, SpellTransporterMalfunctionMiss); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - int r = RandomHelper.IRand(0, 119); - if (r < 20) // Transporter Malfunction - 1/6 polymorph - caster.CastSpell(caster, SpellTransporterMalfunctionPolymorph, true); - else if (r < 100) // Evil Twin - 4/6 evil twin - caster.CastSpell(caster, SpellTransporterEvilTwin, true); - else // Transporter Malfunction - 1/6 miss the target - caster.CastSpell(caster, SpellTransporterMalfunctionMiss, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // 28880 - Warrior - // 59542 - Paladin - // 59543 - Hunter - // 59544 - Priest - // 59545 - Death Knight - // 59547 - Shaman - // 59548 - Mage - [Script] // 121093 - Monk - class spell_gen_gift_of_naaru : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || aurEff.GetTotalTicks() == 0) - return; - - float healPct = GetEffectInfo(1).CalcValue() / 100.0f; - float heal = healPct * GetCaster().GetMaxHealth(); - int healTick = (int)Math.Floor(heal / aurEff.GetTotalTicks()); - amount += healTick; - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.PeriodicHeal)); - } - } - - [Script] - class spell_gen_gnomish_transporter : SpellScript - { - const uint SpellTransporterSuccess = 23441; - const uint SpellTransporterFailure = 23446; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellTransporterSuccess, SpellTransporterFailure); - } - - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), RandomHelper.randChance(50) ? SpellTransporterSuccess : SpellTransporterFailure, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 69641 - Gryphon/Wyvern Pet - Mounting Check Aura - class spell_gen_gryphon_wyvern_mount_check : AuraScript - { - void HandleEffectPeriodic(AuraEffect aurEff) - { - Unit target = GetTarget(); - Unit owner = target.GetOwner(); - - if (owner == null) - return; - - if (owner.IsMounted()) - target.SetDisableGravity(true); - else - target.SetDisableGravity(false); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } - } - - //20538 - Hate to Zero(AoE) - //26569 - Hate to Zero(AoE) - //26637 - Hate to Zero(AoE, Unique) - //37326 - Hate to Zero(AoE) - //40410 - Hate to Zero(Should be added, AoE) - //40467 - Hate to Zero(Should be added, AoE) - [Script] //41582 - Hate to Zero(Should be added, Melee) - class spell_gen_hate_to_zero : SpellScript - { - void HandleDummy(uint effIndex) - { - if (GetCaster().CanHaveThreatList()) - GetCaster().GetThreatManager().ModifyThreatByPercent(GetHitUnit(), -100); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // This spell is used by both player and creature, but currently works only if used by player - [Script] // 63984 - Hate to Zero - class spell_gen_hate_to_zero_caster_target : SpellScript - { - void HandleDummy(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - if (target.CanHaveThreatList()) - target.GetThreatManager().ModifyThreatByPercent(GetCaster(), -100); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 19707 - Hate to 50% - class spell_gen_hate_to_50 : SpellScript - { - void HandleDummy(uint effIndex) - { - if (GetCaster().CanHaveThreatList()) - GetCaster().GetThreatManager().ModifyThreatByPercent(GetHitUnit(), -50); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 26886 - Hate to 75% - class spell_gen_hate_to_75 : SpellScript - { - void HandleDummy(uint effIndex) - { - if (GetCaster().CanHaveThreatList()) - GetCaster().GetThreatManager().ModifyThreatByPercent(GetHitUnit(), -25); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // 32748 - Deadly Throw Interrupt - [Script] // 44835 - Maim Interrupt - class spell_gen_interrupt : AuraScript - { - const uint SpellGenThrowInterrupt = 32747; - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellGenThrowInterrupt); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellGenThrowInterrupt, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script("spell_pal_blessing_of_kings")] - [Script("spell_pal_blessing_of_might")] - [Script("spell_dru_mark_of_the_wild")] - [Script("spell_pri_power_word_fortitude")] - [Script("spell_pri_shadow_protection")] - class spell_gen_increase_stats_buff : SpellScript - { - void HandleDummy(uint effIndex) - { - if (GetHitUnit().IsInRaidWith(GetCaster())) - GetCaster().CastSpell(GetCaster(), (uint)(GetEffectValue() + 1), true); // raid buff - else - GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); // single-target buff - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script("spell_hexlord_lifebloom", SpellHexlordMalacrassLifebloomFinalHeal)] - [Script("spell_tur_ragepaw_lifebloom", SpellTurRagepawLifebloomFinalHeal)] - [Script("spell_cenarion_scout_lifebloom", SpellCenarionScoutLifebloomFinalHeal)] - [Script("spell_twisted_visage_lifebloom", SpellTwistedVisageLifebloomFinalHeal)] - [Script("spell_faction_champion_dru_lifebloom", SpellFactionChapionsDruLifebloomFinalHeal)] - class spell_gen_lifebloom : AuraScript - { - const uint SpellHexlordMalacrassLifebloomFinalHeal = 43422; - const uint SpellTurRagepawLifebloomFinalHeal = 52552; - const uint SpellCenarionScoutLifebloomFinalHeal = 53692; - const uint SpellTwistedVisageLifebloomFinalHeal = 57763; - const uint SpellFactionChapionsDruLifebloomFinalHeal = 66094; - - uint _spellId; - - public spell_gen_lifebloom(uint spellId) - { - _spellId = spellId; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_spellId); - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // final heal only on duration end or dispel - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire && GetTargetApplication().GetRemoveMode() != AuraRemoveMode.EnemySpell) - return; - - // final heal - GetTarget().CastSpell(GetTarget(), _spellId, new CastSpellExtraArgs(aurEff).SetOriginalCaster(GetCasterGUID())); - } - - public override void Register() - { - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.Real)); - } - } - - [Script] - class spell_gen_mounted_charge : SpellScript - { - const uint SpellChargeDamage8K5 = 62874; - const uint SpellChargeDamage20K = 68498; - const uint SpellChargeDamage45K = 64591; - - const uint SpellChargeChargingEffect8K5 = 63661; - const uint SpellChargeCharging20K1 = 68284; - const uint SpellChargeCharging20K2 = 68501; - const uint SpellChargeCharging45K1 = 62563; - const uint SpellChargeCharging45K2 = 66481; - - const uint SpellChargeTriggerFactionMounts = 62960; - const uint SpellChargeTriggerTrialChapion = 68282; - - const uint SpellChargeMissEffect = 62977; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(62552, 62719, 64100, 66482); - } - - void HandleScriptEffect(uint effIndex) - { - Unit target = GetHitUnit(); - - switch (effIndex) - { - case 0: // On spells wich trigger the damaging spell (and also the visual) - { - uint spellId; - - switch (GetSpellInfo().Id) - { - case SpellChargeTriggerTrialChapion: - spellId = SpellChargeCharging20K1; - break; - case SpellChargeTriggerFactionMounts: - spellId = SpellChargeChargingEffect8K5; - break; - default: - return; - } - - // If target isn't a training dummy there's a chance of failing the charge - if (!target.IsCharmedOwnedByPlayerOrPlayer() && RandomHelper.randChance(12.5f)) - spellId = SpellChargeMissEffect; - - Unit vehicle = GetCaster().GetVehicleBase(); - if (vehicle != null) - vehicle.CastSpell(target, spellId, false); - else - GetCaster().CastSpell(target, spellId, false); - break; - } - case 1: // On damaging spells, for removing a defend layer - case 2: - { - var auras = target.GetAppliedAuras(); - foreach (var pair in auras) - { - Aura aura = pair.Value.GetBase(); - if (aura != null) - { - if (aura.GetId() == 62552 || aura.GetId() == 62719 || aura.GetId() == 64100 || aura.GetId() == 66482) - { - aura.ModStackAmount(-1, AuraRemoveMode.EnemySpell); - // Remove dummys from rider (Necessary for updating visual shields) - Unit rider = target.GetCharmer(); - if (rider != null) - { - Aura defend = rider.GetAura(aura.GetId()); - if (defend != null) - defend.ModStackAmount(-1, AuraRemoveMode.EnemySpell); - } - break; - } - } - } - break; - } - default: - break; - } - } - - void HandleChargeEffect(uint effIndex) - { - uint spellId; - - switch (GetSpellInfo().Id) - { - case SpellChargeChargingEffect8K5: - spellId = SpellChargeDamage8K5; - break; - case SpellChargeCharging20K1: - case SpellChargeCharging20K2: - spellId = SpellChargeDamage20K; - break; - case SpellChargeCharging45K1: - case SpellChargeCharging45K2: - spellId = SpellChargeDamage45K; - break; - default: - return; - } - - Unit rider = GetCaster().GetCharmer(); - if (rider != null) - rider.CastSpell(GetHitUnit(), spellId, false); - else - GetCaster().CastSpell(GetHitUnit(), spellId, false); - } - - public override void Register() - { - SpellInfo spell = SpellMgr.GetSpellInfo(m_scriptSpellId, Difficulty.None); - - if (spell.HasEffect(SpellEffectName.ScriptEffect)) - OnEffectHitTarget.Add(new(HandleScriptEffect, SpellConst.EffectFirstFound, SpellEffectName.ScriptEffect)); - - if (spell.GetEffect(0).IsEffect(SpellEffectName.Charge)) - OnEffectHitTarget.Add(new(HandleChargeEffect, 0, SpellEffectName.Charge)); - } - } - - // 6870 Moss Covered Feet - [Script] // 31399 Moss Covered Feet - class spell_gen_moss_covered_feet : AuraScript - { - const uint SpellFallDown = 6869; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFallDown); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - eventInfo.GetActionTarget().CastSpell(null, SpellFallDown, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 28702 - Netherbloom - class spell_gen_netherbloom : SpellScript - { - const uint SpellNetherbloomPollen1 = 28703; - - public override bool Validate(SpellInfo spellInfo) - { - for (byte i = 0; i < 5; ++i) - if (!ValidateSpellInfo(SpellNetherbloomPollen1 + i)) - return false; - - return true; - } - - void HandleScript(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - - Unit target = GetHitUnit(); - if (target != null) - { - // 25% chance of casting a random buff - if (RandomHelper.randChance(75)) - return; - - // triggered spells are 28703 to 28707 - // Note: some sources say, that there was the possibility of - // receiving a debuff. However, this seems to be Removed by a patch. - - // don't overwrite an existing aura - for (byte i = 0; i < 5; ++i) - if (target.HasAura(SpellNetherbloomPollen1 + i)) - return; - - target.CastSpell(target, SpellNetherbloomPollen1 + RandomHelper.URand(0, 4), true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 28720 - Nightmare Vine - class spell_gen_nightmare_vine : SpellScript - { - const uint SpellNightmarePollen = 28721; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellNightmarePollen); - } - - void HandleScript(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - - Unit target = GetHitUnit(); - if (target != null) - { - // 25% chance of casting Nightmare Pollen - if (RandomHelper.randChance(25)) - target.CastSpell(target, SpellNightmarePollen, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 27746 - Nitrous Boost - class spell_gen_nitrous_boost : AuraScript - { - void PeriodicTick(AuraEffect aurEff) - { - PreventDefaultAction(); - - if (GetCaster() != null && GetTarget().GetPower(PowerType.Mana) >= 10) - GetTarget().ModifyPower(PowerType.Mana, -10); - else - Remove(); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 1, AuraType.PeriodicTriggerSpell)); - } - } - - [Script] // 27539 - Obsidian Armor - class spell_gen_obsidian_armor : AuraScript - { - const uint SpellGenObsidianArmorHoly = 27536; - const uint SpellGenObsidianArmorFire = 27533; - const uint SpellGenObsidianArmorNature = 27538; - const uint SpellGenObsidianArmorFrost = 27534; - const uint SpellGenObsidianArmorShadow = 27535; - const uint SpellGenObsidianArmorArcane = 27540; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellGenObsidianArmorHoly, SpellGenObsidianArmorFire, SpellGenObsidianArmorNature, SpellGenObsidianArmorFrost, SpellGenObsidianArmorShadow, SpellGenObsidianArmorArcane); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - if (eventInfo.GetSpellInfo() == null) - return false; - - if (SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask()) == SpellSchools.Normal) - return false; - - return true; - } - - void OnProcEffect(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - uint spellId; - switch (SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask())) - { - case SpellSchools.Holy: - spellId = SpellGenObsidianArmorHoly; - break; - case SpellSchools.Fire: - spellId = SpellGenObsidianArmorFire; - break; - case SpellSchools.Nature: - spellId = SpellGenObsidianArmorNature; - break; - case SpellSchools.Frost: - spellId = SpellGenObsidianArmorFrost; - break; - case SpellSchools.Shadow: - spellId = SpellGenObsidianArmorShadow; - break; - case SpellSchools.Arcane: - spellId = SpellGenObsidianArmorArcane; - break; - default: - return; - } - GetTarget().CastSpell(GetTarget(), spellId, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(OnProcEffect, 0, AuraType.Dummy)); - } - } - - [Script] - class spell_gen_oracle_wolvar_reputation : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) + // Here the target is the water spout and determines the position where the player is knocked from + Unit target = GetHitUnit(); + if (target != null) { Player player = GetCaster().ToPlayer(); - uint factionId = (uint)GetEffectInfo().CalcValue(); - int repChange = GetEffectInfo(1).CalcValue(); - - var factionEntry = CliDB.FactionStorage.LookupByKey(factionId); - if (factionEntry == null) - return; - - // Set rep to baserep + basepoints (expecting spillover for oposite faction . become hated) - // Not when player already has equal or higher rep with this faction - if (player.GetReputationMgr().GetReputation(factionEntry) < repChange) - player.GetReputationMgr().SetReputation(factionEntry, repChange); - - // EffectIndex2 most likely update at war state, we already handle this in SetReputation - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_gen_orc_disguise : SpellScript - { - const uint SpellOrcDisguiseTrigger = 45759; - const uint SpellOrcDisguiseMale = 45760; - const uint SpellOrcDisguiseFemale = 45762; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellOrcDisguiseTrigger, SpellOrcDisguiseMale, SpellOrcDisguiseFemale); - } - - void HandleScript(uint effIndex) - { - Unit caster = GetCaster(); - Player target = GetHitPlayer(); - if (target != null) - { - if (target.GetNativeGender() == 0) - caster.CastSpell(target, SpellOrcDisguiseMale, true); - else - caster.CastSpell(target, SpellOrcDisguiseFemale, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 35201 - Paralytic Poison - class spell_gen_paralytic_poison : AuraScript - { - const uint SpellParalysis = 35202; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellParalysis); - } - - void HandleStun(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; - - GetTarget().CastSpell(null, SpellParalysis, aurEff); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleStun, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); - } - } - - [Script] - class spell_gen_prevent_emotes : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, SpellConst.EffectFirstFound, AuraType.Any, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, SpellConst.EffectFirstFound, AuraType.Any, AuraEffectHandleModes.Real)); - } - } - - [Script] - class spell_gen_player_say : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return CliDB.BroadcastTextStorage.HasRecord((uint)spellInfo.GetEffect(0).CalcValue()); - } - - void HandleScript(uint effIndex) - { - // Note: target here is always player; caster here is gameobj, creature or player (self cast) - Unit target = GetHitUnit(); - if (target != null) - target.Say((uint)GetEffectValue(), target); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script("spell_item_soul_harvesters_charm")] - [Script("spell_item_commendation_of_kaelthas")] - [Script("spell_item_corpse_tongue_coin")] - [Script("spell_item_corpse_tongue_coin_heroic")] - [Script("spell_item_petrified_twilight_scale")] - [Script("spell_item_petrified_twilight_scale_heroic")] - class spell_gen_proc_below_pct_damaged : AuraScript - { - bool CheckProc(ProcEventInfo eventInfo) - { - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return false; - - int pct = GetSpellInfo().GetEffect(0).CalcValue(); - - if (eventInfo.GetActionTarget().HealthBelowPctDamaged(pct, damageInfo.GetDamage())) - return true; - - return false; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } - } - - [Script] - class spell_gen_proc_charge_drop_only : AuraScript - { - void HandleChargeDrop(ProcEventInfo eventInfo) - { - PreventDefaultAction(); - } - - public override void Register() - { - OnProc.Add(new(HandleChargeDrop)); - } - } - - [Script] // 45472 Parachute - class spell_gen_parachute : AuraScript - { - const uint SpellParachute = 45472; - const uint SpellParachuteBuff = 44795; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellParachute, SpellParachuteBuff); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - Player target = GetTarget().ToPlayer(); - if (target != null) - if (target.IsFalling()) - { - target.RemoveAurasDueToSpell(SpellParachute); - target.CastSpell(target, SpellParachuteBuff, true); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } - } - - [Script] - class spell_gen_pet_summoned : SpellScript - { - const uint NpcDoomguard = 11859; - const uint NpcInfernal = 89; - const uint NpcImp = 416; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - Player player = GetCaster().ToPlayer(); - if (player.GetLastPetNumber() != 0) - { - PetType newPetType = (player.GetClass() == Class.Hunter) ? PetType.Hunter : PetType.Summon; - Pet newPet = new Pet(player, newPetType); - if (newPet.LoadPetFromDB(player, 0, player.GetLastPetNumber(), true)) - { - // revive the pet if it is dead - if (newPet.GetDeathState() != DeathState.Alive && newPet.GetDeathState() != DeathState.JustRespawned) - newPet.SetDeathState(DeathState.JustRespawned); - - newPet.SetFullHealth(); - newPet.SetFullPower(newPet.GetPowerType()); - - switch (newPet.GetEntry()) - { - case NpcDoomguard: - case NpcInfernal: - newPet.SetEntry(NpcImp); - break; - default: - break; - } - } - else - newPet.Dispose(); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 36553 - PetWait - class spell_gen_pet_wait : SpellScript - { - void HandleScript(uint effIndex) - { - GetCaster().GetMotionMaster().Clear(); - GetCaster().GetMotionMaster().MoveIdle(); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_profession_research : SpellScript - { - const uint SpellNorthrendInscriptionResearch = 61177; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - SpellCastResult CheckRequirement() - { - Player player = GetCaster().ToPlayer(); - - if (SkillDiscovery.HasDiscoveredAllSpells(GetSpellInfo().Id, player)) - { - SetCustomCastResultMessage(SpellCustomErrors.NothingToDiscover); - return SpellCastResult.CustomError; - } - - return SpellCastResult.SpellCastOk; - } - - void HandleScript(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - uint spellId = GetSpellInfo().Id; - - // Learn random explicit discovery recipe (if any) - // Players will now learn 3 recipes the very first time they perform Northrend Inscription Research (3.3.0 patch notes) - if (spellId == SpellNorthrendInscriptionResearch && !SkillDiscovery.HasDiscoveredAnySpell(spellId, caster)) - { - for (int i = 0; i < 2; ++i) - { - uint discoveredSpellId = SkillDiscovery.GetExplicitDiscoverySpell(spellId, caster); - if (discoveredSpellId != 0) - caster.LearnSpell(discoveredSpellId, false); - } - } - - uint discoveredSpellId1 = SkillDiscovery.GetExplicitDiscoverySpell(spellId, caster); - if (discoveredSpellId1 != 0) - caster.LearnSpell(discoveredSpellId1, false); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckRequirement)); - OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_pvp_trinket : SpellScript - { - const uint SpellPvpTrinketAlliance = 97403; - const uint SpellPvpTrinketHorde = 97404; - - void TriggerAnimation() - { - Player caster = GetCaster().ToPlayer(); - - switch (caster.GetEffectiveTeam()) - { - case Team.Alliance: - caster.CastSpell(caster, SpellPvpTrinketAlliance, TriggerCastFlags.FullMask); - break; - case Team.Horde: - caster.CastSpell(caster, SpellPvpTrinketHorde, TriggerCastFlags.FullMask); - break; - default: - break; - } - } - - public override void Register() - { - AfterCast.Add(new(TriggerAnimation)); - } - } - - [Script] - class spell_gen_Remove_flight_auras : SpellScript - { - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - { - target.RemoveAurasByType(AuraType.Fly); - target.RemoveAurasByType(AuraType.ModIncreaseMountedFlightSpeed); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 20589 - Escape artist - class spell_gen_Remove_impairing_auras : SpellScript - { - void HandleScriptEffect(uint effIndex) - { - GetHitUnit().RemoveMovementImpairingAuras(true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } - } - - // 23493 - Restoration - [Script] // 24379 - Restoration - class spell_gen_restoration : AuraScript - { - void PeriodicTick(AuraEffect aurEff) - { - PreventDefaultAction(); - - Unit target = GetTarget(); - if (target == null) - return; - - uint heal = (uint)target.CountPctFromMaxHealth(10); - HealInfo healInfo = new(target, target, heal, GetSpellInfo(), GetSpellInfo().GetSchoolMask()); - target.HealBySpell(healInfo); - - /// @todo: should proc other auras? - int mana = target.GetMaxPower(PowerType.Mana); - if (mana != 0) - { - mana /= 10; - target.EnergizeBySpell(target, GetSpellInfo(), mana, PowerType.Mana); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicTriggerSpell)); - } - } - - // 38772 Grievous Wound - // 43937 Grievous Wound - // 62331 Impale - [Script] // 62418 Impale - class spell_gen_Remove_on_health_pct : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - void PeriodicTick(AuraEffect aurEff) - { - // they apply damage so no need to check for ticks here - - if (GetTarget().HealthAbovePct(GetEffectInfo(1).CalcValue())) - { - Remove(AuraRemoveMode.EnemySpell); - PreventDefaultAction(); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicDamage)); - } - } - - // 31956 Grievous Wound - // 38801 Grievous Wound - // 43093 Grievous Throw - // 58517 Grievous Wound - [Script] // 59262 Grievous Wound - class spell_gen_Remove_on_full_health : AuraScript - { - void PeriodicTick(AuraEffect aurEff) - { - // if it has only periodic effect, allow 1 tick - bool onlyEffect = GetSpellInfo().GetEffects().Count == 1; - if (onlyEffect && aurEff.GetTickNumber() <= 1) - return; - - if (GetTarget().IsFullHealth()) - { - Remove(AuraRemoveMode.EnemySpell); - PreventDefaultAction(); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicDamage)); - } - } - - // 70292 - Glacial Strike - [Script] // 71316 - Glacial Strike - class spell_gen_Remove_on_full_health_pct : AuraScript - { - void PeriodicTick(AuraEffect aurEff) - { - // they apply damage so no need to check for ticks here - - if (GetTarget().IsFullHealth()) - { - Remove(AuraRemoveMode.EnemySpell); - PreventDefaultAction(); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 2, AuraType.PeriodicDamagePercent)); - } - } - - class ReplenishmentCheck : ICheck - { - public bool Invoke(WorldObject obj) - { - Unit target = obj.ToUnit(); - if (target != null) - return target.GetPowerType() != PowerType.Mana; - - return true; - } - } - - [Script] - class spell_gen_replenishment : SpellScript - { - void RemoveInvalidTargets(List targets) - { - // In arenas Replenishment may only affect the caster - Player caster = GetCaster().ToPlayer(); - if (caster != null) - { - if (caster.InArena()) - { - targets.Clear(); - targets.Add(caster); - return; - } - } - - targets.RemoveAll(new ReplenishmentCheck()); - - byte maxTargets = 10; - - if (targets.Count > maxTargets) - { - targets.Sort(new PowerPctOrderPred(PowerType.Mana)); - targets.Resize(maxTargets); - } - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(RemoveInvalidTargets, SpellConst.EffectAll, Targets.UnitCasterAreaRaid)); - } - } - - [Script] - class spell_gen_replenishment_AuraScript : AuraScript - { - const uint SpellReplenishment = 57669; - const uint SpellInfiniteReplenishment = 61782; - - public override bool Load() - { - return GetUnitOwner().GetPowerType() == PowerType.Mana; - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - switch (GetSpellInfo().Id) - { - case SpellReplenishment: - amount = (int)(GetUnitOwner().GetMaxPower(PowerType.Mana) * 0.002f); - break; - case SpellInfiniteReplenishment: - amount = (int)(GetUnitOwner().GetMaxPower(PowerType.Mana) * 0.0025f); - break; - default: - break; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.PeriodicEnergize)); - } - } - - struct RunningWildMountIds - { - public const uint AlteredForm = 97709; - } - - [Script] - class spell_gen_running_wild : SpellScript - { - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(RunningWildMountIds.AlteredForm); - } - - public override void OnPrecast() - { - GetCaster().CastSpell(GetCaster(), RunningWildMountIds.AlteredForm, TriggerCastFlags.FullMask); - } - - public override void Register() - { - } - } - - [Script] - class spell_gen_running_wild_AuraScript : AuraScript - { - public override bool Validate(SpellInfo spell) - { - if (!CliDB.CreatureDisplayInfoStorage.ContainsKey(SharedConst.DisplayIdHiddenMount)) - return false; - return true; - } - - void HandleMount(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - PreventDefaultAction(); - - target.Mount(SharedConst.DisplayIdHiddenMount, 0, 0); - - // cast speed aura - var mountCapability = CliDB.MountCapabilityStorage.LookupByKey(aurEff.GetAmount()); - if (mountCapability != null) - target.CastSpell(target, mountCapability.ModSpellAuraID, TriggerCastFlags.FullMask); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleMount, 1, AuraType.Mounted, AuraEffectHandleModes.Real)); - } - } - - [Script] - class spell_gen_two_forms : SpellScript - { - SpellCastResult CheckCast() - { - if (GetCaster().IsInCombat()) - { - SetCustomCastResultMessage(SpellCustomErrors.CantTransform); - return SpellCastResult.CustomError; - } - - // Player cannot transform to human form if he is forced to be worgen for some reason (Darkflight) - var alteredFormAuras = GetCaster().GetAuraEffectsByType(AuraType.WorgenAlteredForm); - if (alteredFormAuras.Count > 1) - { - SetCustomCastResultMessage(SpellCustomErrors.CantTransform); - return SpellCastResult.CustomError; - } - - return SpellCastResult.SpellCastOk; - } - - void HandleTransform(uint effIndex) - { - Unit target = GetHitUnit(); - PreventHitDefaultEffect(effIndex); - if (target.HasAuraType(AuraType.WorgenAlteredForm)) - target.RemoveAurasByType(AuraType.WorgenAlteredForm); - else // Basepoints 1 for this aura control whether to trigger transform transition animation or not. - target.CastSpell(target, RunningWildMountIds.AlteredForm, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, 1)); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(HandleTransform, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_gen_darkflight : SpellScript - { - void TriggerTransform() - { - GetCaster().CastSpell(GetCaster(), RunningWildMountIds.AlteredForm, TriggerCastFlags.FullMask); - } - - public override void Register() - { - AfterCast.Add(new(TriggerTransform)); - } - } - - [Script] - class spell_gen_seaforium_blast : SpellScript - { - const uint SpellPlantChargesCreditAchievement = 60937; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellPlantChargesCreditAchievement); - } - - public override bool Load() - { - return GetGObjCaster().GetOwnerGUID().IsPlayer(); - } - - void AchievementCredit(uint effIndex) - { - Unit owner = GetGObjCaster().GetOwner(); - if (owner != null) - { - GameObject go = GetHitGObj(); - if (go != null) - if (go.GetGoInfo().type == GameObjectTypes.DestructibleBuilding) - owner.CastSpell(null, SpellPlantChargesCreditAchievement, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(AchievementCredit, 1, SpellEffectName.GameObjectDamage)); - } - } - - [Script] - class spell_gen_spectator_cheer_trigger : SpellScript - { - Emote[] EmoteArray = { Emote.OneshotCheer, Emote.OneshotExclamation, Emote.OneshotApplaud }; - - void HandleDummy(uint effIndex) - { - if (RandomHelper.randChance(40)) - GetCaster().HandleEmoteCommand(EmoteArray.SelectRandom()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_gen_spirit_healer_res : SpellScript - { - public override bool Load() - { - return GetOriginalCaster() != null && GetOriginalCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) - { - Player originalCaster = GetOriginalCaster().ToPlayer(); - Unit target = GetHitUnit(); - if (target != null) - { - NPCInteractionOpenResult spiritHealerConfirm = new(); - spiritHealerConfirm.Npc = target.GetGUID(); - spiritHealerConfirm.InteractionType = PlayerInteractionType.SpiritHealer; - spiritHealerConfirm.Success = true; - originalCaster.SendPacket(spiritHealerConfirm); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_gen_summon_tournament_mount : SpellScript - { - const uint SpellLanceEquipped = 62853; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellLanceEquipped); - } - - SpellCastResult CheckIfLanceEquiped() - { - if (GetCaster().IsInDisallowedMountForm()) - GetCaster().RemoveAurasByType(AuraType.ModShapeshift); - - if (!GetCaster().HasAura(SpellLanceEquipped)) - { - SetCustomCastResultMessage(SpellCustomErrors.MustHaveLanceEquipped); - return SpellCastResult.CustomError; - } - - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckIfLanceEquiped)); - } - } - - [Script] // 41213, 43416, 69222, 73076 - Throw Shield - class spell_gen_throw_shield : SpellScript - { - void HandleScriptEffect(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_tournament_duel : SpellScript - { - const uint SpellOnTournamentMount = 63034; - const uint SpellMountedDuel = 62875; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellOnTournamentMount, SpellMountedDuel); - } - - void HandleScriptEffect(uint effIndex) - { - Unit rider = GetCaster().GetCharmer(); - if (rider != null) - { - Player playerTarget = GetHitPlayer(); - if (playerTarget != null) - { - if (playerTarget.HasAura(SpellOnTournamentMount) && playerTarget.GetVehicleBase() != null) - rider.CastSpell(playerTarget, SpellMountedDuel, true); - } - else - { - Unit unitTarget = GetHitUnit(); - if (unitTarget != null) - { - if (unitTarget.GetCharmer() != null && unitTarget.GetCharmer().IsPlayer() && unitTarget.GetCharmer().HasAura(SpellOnTournamentMount)) - rider.CastSpell(unitTarget.GetCharmer(), SpellMountedDuel, true); - } - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_tournament_pennant : AuraScript - { - public override bool Load() - { - return GetCaster() != null && GetCaster().IsPlayer(); - } - - void HandleApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - if (caster.GetVehicleBase() == null) - caster.RemoveAurasDueToSpell(GetId()); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleApplyEffect, 0, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); - } - } - - [Script] - class spell_gen_teleporting : SpellScript - { - const uint AreaVioletCitadelSpire = 4637; - - const uint SpellTeleportSpireDown = 59316; - const uint SpellTeleportSpireUp = 59314; - - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - if (!target.IsPlayer()) - return; - - // return from top - if (target.ToPlayer().GetAreaId() == AreaVioletCitadelSpire) - target.CastSpell(target, SpellTeleportSpireDown, true); - // teleport atop - else - target.CastSpell(target, SpellTeleportSpireUp, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_trigger_exclude_caster_aura_spell : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(spellInfo.ExcludeCasterAuraSpell); - } - - void HandleTrigger() - { - // Blizz seems to just apply aura without bothering to cast - GetCaster().AddAura(GetSpellInfo().ExcludeCasterAuraSpell, GetCaster()); - } - - public override void Register() - { - AfterCast.Add(new(HandleTrigger)); - } - } - - [Script] - class spell_gen_trigger_exclude_target_aura_spell : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(spellInfo.ExcludeTargetAuraSpell); - } - - void HandleTrigger() - { - Unit target = GetHitUnit(); - if (target != null) - // Blizz seems to just apply aura without bothering to cast - GetCaster().AddAura(GetSpellInfo().ExcludeTargetAuraSpell, target); - } - - public override void Register() - { - AfterHit.Add(new(HandleTrigger)); - } - } - - [Script("spell_pvp_trinket_shared_cd", SpellWillOfTheForsakenCooldownTrigger)] - [Script("spell_wotf_shared_cd", SpellWillOfTheForsakenCooldownTriggerWotf)] - class spell_pvp_trinket_wotf_shared_cd : SpellScript - { - const uint SpellWillOfTheForsakenCooldownTrigger = 72752; - const uint SpellWillOfTheForsakenCooldownTriggerWotf = 72757; - - uint _triggeredSpellId; - - public spell_pvp_trinket_wotf_shared_cd(uint triggeredSpellId) - { - _triggeredSpellId = triggeredSpellId; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_triggeredSpellId); - } - - void HandleScript() - { - // Spell flags need further research, until then just cast not triggered - GetCaster().CastSpell(null, _triggeredSpellId, false); - } - - public override void Register() - { - AfterCast.Add(new(HandleScript)); - } - } - - [Script] - class spell_gen_turkey_marker : AuraScript - { - const uint SpellTurkeyVengeance = 25285; - - List _applyTimes = new(); - - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // store stack apply times, so we can pop them while they expire - _applyTimes.Add(GameTime.GetGameTimeMS()); - Unit target = GetTarget(); - - // on stack 15 cast the achievement crediting spell - if (GetStackAmount() >= 15) - target.CastSpell(target, SpellTurkeyVengeance, new CastSpellExtraArgs(aurEff) - .SetOriginalCaster(GetCasterGUID())); - } - - void OnPeriodic(AuraEffect aurEff) - { - int RemoveCount = 0; - - // pop expired times off of the stack - while (!_applyTimes.Empty() && _applyTimes.First() + GetMaxDuration() < GameTime.GetGameTimeMS()) - { - _applyTimes.RemoveAt(0); - RemoveCount++; - } - - if (RemoveCount != 0) - ModStackAmount(-RemoveCount, AuraRemoveMode.Expire); - } - - public override void Register() - { - AfterEffectApply.Add(new(OnApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); - OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicDummy)); - } - } - - [Script] - class spell_gen_upper_deck_create_foam_sword : SpellScript - { - uint[] itemId = { 45061, 45176, 45177, 45178, 45179 }; - - void HandleScript(uint effIndex) - { - Player player = GetHitPlayer(); if (player != null) { + float horizontalSpeed = 20.0f + (40.0f - GetCaster().GetDistance(target)); + float verticalSpeed = 8.0f; + // This method relies on the Dalaran Sewer map disposition and Water Spout position + // What we do is knock the player from a position exactly behind him and at the end of the pipe + player.KnockbackFrom(target.GetPosition(), horizontalSpeed, verticalSpeed); + } + } + } - // player can only have one of these items - for (byte i = 0; i < 5; ++i) + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 50051 - Ethereal Pet Aura +class spell_ethereal_pet_aura : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) + { + uint levelDiff = (uint)Math.Abs(GetTarget().GetLevel() - eventInfo.GetProcTarget().GetLevel()); + return levelDiff <= 9; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + List minionList = GetUnitOwner().GetAllMinionsByEntry(CreatureIds.EtherealSoulTrader); + foreach (Creature minion in minionList) + { + if (minion.IsAIEnabled()) + { + minion.GetAI().Talk(MiscConst.SayStealEssence); + minion.CastSpell(eventInfo.GetProcTarget(), SpellIds.StealEssenceVisual); + } + } + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 50052 - Ethereal Pet onSummon +class spell_ethereal_pet_onsummon : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ProcTriggerOnKillAura); + } + + void HandleScriptEffect(uint effIndex) + { + Unit target = GetHitUnit(); + target.CastSpell(target, SpellIds.ProcTriggerOnKillAura, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 50055 - Ethereal Pet Aura Remove +class spell_ethereal_pet_aura_remove : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EtherealPetAura); + } + + void HandleScriptEffect(uint effIndex) + { + GetHitUnit().RemoveAurasDueToSpell(SpellIds.EtherealPetAura); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 50101 - Ethereal Pet OnKill Steal Essence +class spell_steal_essence_visual : AuraScript +{ + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + { + caster.CastSpell(caster, SpellIds.CreateToken, true); + Creature soulTrader = caster.ToCreature(); + if (soulTrader != null) + soulTrader.GetAI().Talk(MiscConst.SayCreateToken); + } + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +/* 57337 - Great Feast + 57397 - Fish Feast + 58466 - Gigantic Feast + 58475 - Small Feast + 66477 - Bountiful Feast */ +[Script] +class spell_gen_feast : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FeastFood, SpellIds.FeastDrink, SpellIds.BountifulFeastDrink, SpellIds.BountifulFeastFood, SpellIds.GreatFeastRefreshment, SpellIds.FishFeastRefreshment, SpellIds.GiganticFeastRefreshment, SpellIds.SmallFeastRefreshment, SpellIds.BountifulFeastRefreshment); + } + + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + + switch (GetSpellInfo().Id) + { + case SpellIds.GreatFeast: + target.CastSpell(target, SpellIds.FeastFood); + target.CastSpell(target, SpellIds.FeastDrink); + target.CastSpell(target, SpellIds.GreatFeastRefreshment); + break; + case SpellIds.FishFeast: + target.CastSpell(target, SpellIds.FeastFood); + target.CastSpell(target, SpellIds.FeastDrink); + target.CastSpell(target, SpellIds.FishFeastRefreshment); + break; + case SpellIds.GiganticFeast: + target.CastSpell(target, SpellIds.FeastFood); + target.CastSpell(target, SpellIds.FeastDrink); + target.CastSpell(target, SpellIds.GiganticFeastRefreshment); + break; + case SpellIds.SmallFeast: + target.CastSpell(target, SpellIds.FeastFood); + target.CastSpell(target, SpellIds.FeastDrink); + target.CastSpell(target, SpellIds.SmallFeastRefreshment); + break; + case SpellIds.BountifulFeast: + target.CastSpell(target, SpellIds.BountifulFeastRefreshment); + target.CastSpell(target, SpellIds.BountifulFeastDrink); + target.CastSpell(target, SpellIds.BountifulFeastFood); + break; + default: + break; + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_feign_death_all_flags : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetUnitFlag3(UnitFlags3.FakeDead); + target.SetUnitFlag2(UnitFlags2.FeignDeath); + target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); + + Creature creature = target.ToCreature(); + if (target != null) + creature.SetReactState(ReactStates.Passive); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveUnitFlag3(UnitFlags3.FakeDead); + target.RemoveUnitFlag2(UnitFlags2.FeignDeath); + target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); + + Creature creature = target.ToCreature(); + if (target != null) + creature.InitializeReactState(); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] +class spell_gen_feign_death_all_flags_uninteractible : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetUnitFlag3(UnitFlags3.FakeDead); + target.SetUnitFlag2(UnitFlags2.FeignDeath); + target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); + target.SetImmuneToAll(true); + target.SetUninteractible(true); + + Creature creature = target.ToCreature(); + if (target != null) + creature.SetReactState(ReactStates.Passive); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveUnitFlag3(UnitFlags3.FakeDead); + target.RemoveUnitFlag2(UnitFlags2.FeignDeath); + target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); + target.SetImmuneToAll(false); + target.SetUninteractible(false); + + Creature creature = target.ToCreature(); + if (target != null) + creature.InitializeReactState(); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 96733 - Permanent Feign Death (Stun) +class spell_gen_feign_death_all_flags_no_uninteractible : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetUnitFlag3(UnitFlags3.FakeDead); + target.SetUnitFlag2(UnitFlags2.FeignDeath); + target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); + target.SetImmuneToAll(true); + + Creature creature = target.ToCreature(); + if (target != null) + creature.SetReactState(ReactStates.Passive); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveUnitFlag3(UnitFlags3.FakeDead); + target.RemoveUnitFlag2(UnitFlags2.FeignDeath); + target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); + target.SetImmuneToAll(false); + + Creature creature = target.ToCreature(); + if (target != null) + creature.InitializeReactState(); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +// 35357 - Spawn Feign Death +[Script] // 51329 - Feign Death +class spell_gen_feign_death_no_dyn_flag : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetUnitFlag2(UnitFlags2.FeignDeath); + target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); + + Creature creature = target.ToCreature(); + if (target != null) + creature.SetReactState(ReactStates.Passive); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveUnitFlag2(UnitFlags2.FeignDeath); + target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); + + Creature creature = target.ToCreature(); + if (target != null) + creature.InitializeReactState(); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 58951 - Permanent Feign Death +class spell_gen_feign_death_no_prevent_emotes : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetUnitFlag3(UnitFlags3.FakeDead); + target.SetUnitFlag2(UnitFlags2.FeignDeath); + + Creature creature = target.ToCreature(); + if (target != null) + creature.SetReactState(ReactStates.Passive); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveUnitFlag3(UnitFlags3.FakeDead); + target.RemoveUnitFlag2(UnitFlags2.FeignDeath); + + Creature creature = target.ToCreature(); + if (target != null) + creature.InitializeReactState(); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 35491 - Furious Rage +class spell_gen_furious_rage : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Exhaustion) && + CliDB.BroadcastTextStorage.HasRecord(MiscConst.EmoteFuriousRage) && + CliDB.BroadcastTextStorage.HasRecord(MiscConst.EmoteExhausted); + } + + void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.TextEmote(MiscConst.EmoteFuriousRage, target, false); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit target = GetTarget(); + target.TextEmote(MiscConst.EmoteExhausted, target, false); + target.CastSpell(target, SpellIds.Exhaustion, true); + } + + public override void Register() + { + AfterEffectApply.Add(new(AfterApply, 0, AuraType.ModDamagePercentDone, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.ModDamagePercentDone, AuraEffectHandleModes.Real)); + } +} + +[Script] // 46642 - 5,000 Gold +class spell_gen_5000_gold : SpellScript +{ + void HandleScript(uint effIndex) + { + Player target = GetHitPlayer(); + if (target != null) + target.ModifyMoney(5000 * MoneyConstants.Gold); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 131474 - Fishing +class spell_gen_fishing : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FishingNoFishingPole, SpellIds.FishingWithPole); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleDummy(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + uint spellId; + Item mainHand = GetCaster().ToPlayer().GetItemByPos(InventorySlots.Bag0, EquipmentSlot.MainHand); + if (mainHand == null || mainHand.GetTemplate().GetClass() != ItemClass.Weapon || (ItemSubClassWeapon)mainHand.GetTemplate().GetSubClass() != ItemSubClassWeapon.FishingPole) + spellId = SpellIds.FishingNoFishingPole; + else + spellId = SpellIds.FishingWithPole; + + GetCaster().CastSpell(GetCaster(), spellId, false); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_gen_gadgetzan_transporter_backfire : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TransporterMalfunctionPolymorph, SpellIds.TransporterEvilTwin, SpellIds.TransporterMalfunctionMiss); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + int r = RandomHelper.IRand(0, 119); + if (r < 20) // Transporter Malfunction - 1/6 polymorph + caster.CastSpell(caster, SpellIds.TransporterMalfunctionPolymorph, true); + else if (r < 100) // Evil Twin - 4/6 evil twin + caster.CastSpell(caster, SpellIds.TransporterEvilTwin, true); + else // Transporter Malfunction - 1/6 miss the target + caster.CastSpell(caster, SpellIds.TransporterMalfunctionMiss, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// 28880 - Warrior +// 59542 - Paladin +// 59543 - Hunter +// 59544 - Priest +// 59545 - Death Knight +// 59547 - Shaman +// 59548 - Mage +[Script] // 121093 - Monk +class spell_gen_gift_of_naaru : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + if (GetCaster() == null || aurEff.GetTotalTicks() == 0) + return; + + float healPct = GetEffectInfo(1).CalcValue() / 100.0f; + float heal = healPct * GetCaster().GetMaxHealth(); + int healTick = (int)Math.Floor(heal / aurEff.GetTotalTicks()); + amount += healTick; + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.PeriodicHeal)); + } +} + +[Script] +class spell_gen_gnomish_transporter : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TransporterSuccess, SpellIds.TransporterFailure); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), RandomHelper.randChance(50) ? SpellIds.TransporterSuccess : SpellIds.TransporterFailure, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 69641 - Gryphon/Wyvern Pet - Mounting Check Aura +class spell_gen_gryphon_wyvern_mount_check : AuraScript +{ + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit target = GetTarget(); + Unit owner = target.GetOwner(); + + if (owner == null) + return; + + if (owner.IsMounted()) + target.SetDisableGravity(true); + else + target.SetDisableGravity(false); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +/* 9204 - Hate to Zero (Melee) + 20538 - Hate to Zero (AoE) + 26569 - Hate to Zero (AoE) + 26637 - Hate to Zero (AoE, Unique) + 37326 - Hate to Zero (AoE) + 40410 - Hate to Zero (Should be added, AoE) + 40467 - Hate to Zero (Should be added, AoE) + 41582 - Hate to Zero (Should be added, Melee) */ +[Script] +class spell_gen_hate_to_zero : SpellScript +{ + void HandleDummy(uint effIndex) + { + if (GetCaster().CanHaveThreatList()) + GetCaster().GetThreatManager().ModifyThreatByPercent(GetHitUnit(), -100); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// This spell is used by both player and creature, but currently works only if used by player +[Script] // 63984 - Hate to Zero +class spell_gen_hate_to_zero_caster_target : SpellScript +{ + void HandleDummy(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) + if (target.CanHaveThreatList()) + target.GetThreatManager().ModifyThreatByPercent(GetCaster(), -100); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 19707 - Hate to 50% +class spell_gen_hate_to_50 : SpellScript +{ + void HandleDummy(uint effIndex) + { + if (GetCaster().CanHaveThreatList()) + GetCaster().GetThreatManager().ModifyThreatByPercent(GetHitUnit(), -50); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 26886 - Hate to 75% +class spell_gen_hate_to_75 : SpellScript +{ + void HandleDummy(uint effIndex) + { + if (GetCaster().CanHaveThreatList()) + GetCaster().GetThreatManager().ModifyThreatByPercent(GetHitUnit(), -25); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// 32748 - Deadly Throw Interrupt +[Script] // 44835 - Maim Interrupt +class spell_gen_interrupt : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GenThrowInterrupt); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.GenThrowInterrupt, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script("spell_pal_blessing_of_kings")] +[Script("spell_pal_blessing_of_might")] +[Script("spell_dru_mark_of_the_wild")] +[Script("spell_pri_power_word_fortitude")] +[Script("spell_pri_shadow_protection")] +class spell_gen_increase_stats_buff : SpellScript +{ + void HandleDummy(uint effIndex) + { + if (GetHitUnit().IsInRaidWith(GetCaster())) + GetCaster().CastSpell(GetCaster(), (uint)GetEffectValue() + 1, true); // raid buff + else + GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); // single-target buff + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script("spell_hexlord_lifebloom", SpellIds.HexlordMalacrassLifebloomFinalHeal)] +[Script("spell_tur_ragepaw_lifebloom", SpellIds.TurRagepawLifebloomFinalHeal)] +[Script("spell_cenarion_scout_lifebloom", SpellIds.CenarionScoutLifebloomFinalHeal)] +[Script("spell_twisted_visage_lifebloom", SpellIds.TwistedVisageLifebloomFinalHeal)] +[Script("spell_faction_champion_dru_lifebloom", SpellIds.FactionChampionsDruLifebloomFinalHeal)] +class spell_gen_lifebloom(uint spellId) : AuraScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(spellId); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // final heal only on duration end or dispel + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire && GetTargetApplication().GetRemoveMode() != AuraRemoveMode.EnemySpell) + return; + + // final heal + GetTarget().CastSpell(GetTarget(), spellId, new CastSpellExtraArgs(aurEff).SetOriginalCaster(GetCasterGUID())); + } + + public override void Register() + { + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.PeriodicHeal, AuraEffectHandleModes.Real)); + } +} + +[Script] +class spell_gen_mounted_charge : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(62552, 62719, 64100, 66482); + } + + void HandleScriptEffect(uint effIndex) + { + Unit target = GetHitUnit(); + + switch (effIndex) + { + case 0: // On spells wich trigger the damaging spell (and also the visual) + { + uint spellId; + + switch (GetSpellInfo().Id) { - if (player.HasItemCount(itemId[i], 1, true)) - return; - } - - CreateItem(itemId[RandomHelper.IRand(0, 4)], ItemContext.None); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - // 52723 - VaMathF.PIric Touch - [Script] // 60501 - VaMathF.PIric Touch - class spell_gen_vapiric_touch : AuraScript - { - const uint SpellVapiricTouchHeal = 52724; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellVapiricTouchHeal); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; - - Unit caster = eventInfo.GetActor(); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)(damageInfo.GetDamage() / 2)); - caster.CastSpell(caster, SpellVapiricTouchHeal, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] - class spell_gen_vehicle_scaling : AuraScript - { - const uint SpellGearScaling = 66668; - - public override bool Load() - { - return GetCaster() != null && GetCaster().IsPlayer(); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit caster = GetCaster(); - float factor; - ushort baseItemLevel; - - /// @todo Reserach coeffs for different vehicles - switch (GetId()) - { - case SpellGearScaling: - factor = 1.0f; - baseItemLevel = 205; - break; - default: - factor = 1.0f; - baseItemLevel = 170; - break; - } - - float avgILvl = caster.ToPlayer().GetAverageItemLevel(); - if (avgILvl < baseItemLevel) - return; /// @todo Research possibility of scaling down - - amount = (ushort)((avgILvl - baseItemLevel) * factor); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModHealingPct)); - DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ModDamagePercentDone)); - DoEffectCalcAmount.Add(new(CalculateAmount, 2, AuraType.ModIncreaseHealthPercent)); - } - } - - [Script] - class spell_gen_vendor_bark_trigger : SpellScript - { - const uint NpcAmphitheaterVendor = 30098; - const uint SayAmphitheaterVendor = 0; - void HandleDummy(uint effIndex) - { - Creature vendor = GetCaster().ToCreature(); - if (vendor != null) - if (vendor.GetEntry() == NpcAmphitheaterVendor) - vendor.GetAI().Talk(SayAmphitheaterVendor); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_gen_wg_water : SpellScript - { - SpellCastResult CheckCast() - { - if (!GetSpellInfo().CheckTargetCreatureType(GetCaster())) - return SpellCastResult.DontReport; - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - } - } - - [Script] - class spell_gen_whisper_gulch_yogg_saron_whisper : AuraScript - { - const uint SpellYoggSaronWhisperDummy = 29072; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellYoggSaronWhisperDummy); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - PreventDefaultAction(); - GetTarget().CastSpell(null, SpellYoggSaronWhisperDummy, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } - } - - [Script] - class spell_gen_whisper_to_controller : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return CliDB.BroadcastTextStorage.HasRecord((uint)spellInfo.GetEffect(0).CalcValue()); - } - - void HandleScript(uint effIndex) - { - TempSummon casterSummon = GetCaster().ToTempSummon(); - if (casterSummon != null) - { - Player target = casterSummon.GetSummonerUnit().ToPlayer(); - if (target != null) - casterSummon.Whisper((uint)GetEffectValue(), target, false); - } - } - - public override void Register() - { - OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - // BasePoints of spells is Id of npc_text used to group texts, it's not implemented so texts are grouped the old way - // 50037 - Mystery of the Infinite: Future You's Whisper to Controller - Random - // 50287 - Azure Dragon: On Death Force Cast Wyrmrest Defender to Whisper to Controller - Random - // 60709 - Moti, Redux: Past You's Whisper to Controller - Random - [Script("spell_future_you_whisper_to_controller_random", WhisperFutureYou)] - [Script("spell_wyrmrest_defender_whisper_to_controller_random", WhisperDefender)] - [Script("spell_past_you_whisper_to_controller_random", WhisperPastYou)] - class spell_gen_whisper_to_controller_random : SpellScript - { - const uint WhisperFutureYou = 2; - const uint WhisperDefender = 1; - const uint WhisperPastYou = 2; - - uint _text; - - public spell_gen_whisper_to_controller_random(uint text) - { - _text = text; - } - - void HandleScript(uint effIndex) - { - // Same for all spells - if (!RandomHelper.randChance(20)) - return; - - Creature target = GetHitCreature(); - if (target != null) - { - TempSummon targetSummon = target.ToTempSummon(); - if (targetSummon != null) - { - Player player = targetSummon.GetSummonerUnit().ToPlayer(); - if (player != null) - targetSummon.GetAI().Talk(_text, player); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - class spell_gen_eject_all_passengers : SpellScript - { - void RemoveVehicleAuras() - { - Vehicle vehicle = GetHitUnit().GetVehicleKit(); - if (vehicle != null) - vehicle.RemoveAllPassengers(); - } - - public override void Register() - { - AfterHit.Add(new(RemoveVehicleAuras)); - } - } - - [Script] - class spell_gen_eject_passenger : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - if (!ValidateSpellEffect((spellInfo.Id, 0))) - return false; - if (spellInfo.GetEffect(0).CalcValue() < 1) - return false; - return true; - } - - void EjectPassenger(uint effIndex) - { - Vehicle vehicle = GetHitUnit().GetVehicleKit(); - if (vehicle != null) - { - Unit passenger = vehicle.GetPassenger((sbyte)(GetEffectValue() - 1)); - if (passenger != null) - passenger.ExitVehicle(); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(EjectPassenger, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script("spell_gen_eject_passenger_1", 0)] - [Script("spell_gen_eject_passenger_3", 2)] - class spell_gen_eject_passenger_with_seatId : SpellScript - { - sbyte _seatId; - - public spell_gen_eject_passenger_with_seatId(int seatId) - { - _seatId = (sbyte)seatId; - } - - void EjectPassenger(uint effIndex) - { - Vehicle vehicle = GetHitUnit().GetVehicleKit(); - if (vehicle != null) - { - Unit passenger = vehicle.GetPassenger(_seatId); - if (passenger != null) - passenger.ExitVehicle(); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(EjectPassenger, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_gen_gm_freeze : AuraScript - { - const uint SpellGmFreeze = 9454; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellGmFreeze); - } - - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // Do what was done before to the target in HandleFreezeCommand - Player player = GetTarget().ToPlayer(); - if (player != null) - { - // stop combat + make player unattackable + duel stop + stop some spells - player.SetFaction((uint)FactionTemplates.Friendly); - player.CombatStop(); - if (player.IsNonMeleeSpellCast(true)) - player.InterruptNonMeleeSpells(true); - player.SetUnitFlag(UnitFlags.NonAttackable); - - // if player class = hunter || warlock Remove pet if alive - if ((player.GetClass() == Class.Hunter) || (player.GetClass() == Class.Warlock)) - { - Pet pet = player.GetPet(); - if (pet != null) - { - pet.SavePetToDB(PetSaveMode.AsCurrent); - // not let dismiss dead pet - if (pet.IsAlive()) - player.RemovePet(pet, PetSaveMode.NotInSlot); - } - } - } - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // Do what was done before to the target in HandleUnfreezeCommand - Player player = GetTarget().ToPlayer(); - if (player != null) - { - // Reset player faction + allow combat + allow duels - player.SetFactionForRace(player.GetRace()); - player.RemoveUnitFlag(UnitFlags.NonAttackable); - // save player - player.SaveToDB(); - } - } - - public override void Register() - { - OnEffectApply.Add(new(OnApply, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); - } - } - - [Script] - class spell_gen_stand : SpellScript - { - void HandleScript(uint eff) - { - Creature target = GetHitCreature(); - if (target == null) - return; - - target.SetStandState(UnitStandStateType.Stand); - target.HandleEmoteCommand(Emote.StateNone); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - struct MixologySpellIds - { - public const uint Mixology = 53042; - // Flasks - public const uint FlaskOfTheFrostWyrm = 53755; - public const uint FlaskOfStoneblood = 53758; - public const uint FlaskOfEndlessRage = 53760; - public const uint FlaskOfPureMojo = 54212; - public const uint LesserFlaskOfResistance = 62380; - public const uint LesserFlaskOfToughness = 53752; - public const uint FlaskOfBlindingLight = 28521; - public const uint FlaskOfChromaticWonder = 42735; - public const uint FlaskOfFortification = 28518; - public const uint FlaskOfMightyRestoration = 28519; - public const uint FlaskOfPureDeath = 28540; - public const uint FlaskOfRelentlessAssault = 28520; - public const uint FlaskOfChromaticResistance = 17629; - public const uint FlaskOfDistilledWisdom = 17627; - public const uint FlaskOfSupremePower = 17628; - public const uint FlaskOfTheTitans = 17626; - // Elixirs - public const uint ElixirOfMightyAgility = 28497; - public const uint ElixirOfAccuracy = 60340; - public const uint ElixirOfDeadlyStrikes = 60341; - public const uint ElixirOfMightyDefense = 60343; - public const uint ElixirOfExpertise = 60344; - public const uint ElixirOfArmorPiercing = 60345; - public const uint ElixirOfLightningSpeed = 60346; - public const uint ElixirOfMightyFortitude = 53751; - public const uint ElixirOfMightyMageblood = 53764; - public const uint ElixirOfMightyStrength = 53748; - public const uint ElixirOfMightyToughts = 60347; - public const uint ElixirOfProtection = 53763; - public const uint ElixirOfSpirit = 53747; - public const uint GurusElixir = 53749; - public const uint ShadowpowerElixir = 33721; - public const uint WrathElixir = 53746; - public const uint ElixirOfEmpowerment = 28514; - public const uint ElixirOfMajorMageblood = 28509; - public const uint ElixirOfMajorShadowPower = 28503; - public const uint ElixirOfMajorDefense = 28502; - public const uint FelStrengthElixir = 38954; - public const uint ElixirOfIronskin = 39628; - public const uint ElixirOfMajorAgility = 54494; - public const uint ElixirOfDraenicWisdom = 39627; - public const uint ElixirOfMajorFirepower = 28501; - public const uint ElixirOfMajorFrostPower = 28493; - public const uint EarthenElixir = 39626; - public const uint ElixirOfMastery = 33726; - public const uint ElixirOfHealingPower = 28491; - public const uint ElixirOfMajorFortitude = 39625; - public const uint ElixirOfMajorStrength = 28490; - public const uint AdeptsElixir = 54452; - public const uint OnslaughtElixir = 33720; - public const uint MightyTrollsBloodElixir = 24361; - public const uint GreaterArcaneElixir = 17539; - public const uint ElixirOfTheMongoose = 17538; - public const uint ElixirOfBruteForce = 17537; - public const uint ElixirOfSages = 17535; - public const uint ElixirOfSuperiorDefense = 11348; - public const uint ElixirOfDemonslaying = 11406; - public const uint ElixirOfGreaterFirepower = 26276; - public const uint ElixirOfShadowPower = 11474; - public const uint MagebloodElixir = 24363; - public const uint ElixirOfGiants = 11405; - public const uint ElixirOfGreaterAgility = 11334; - public const uint ArcaneElixir = 11390; - public const uint ElixirOfGreaterIntellect = 11396; - public const uint ElixirOfGreaterDefense = 11349; - public const uint ElixirOfFrostPower = 21920; - public const uint ElixirOfAgility = 11328; - public const uint MajorTrollsBlloodElixir = 3223; - public const uint ElixirOfFortitude = 3593; - public const uint ElixirOfOgresStrength = 3164; - public const uint ElixirOfFirepower = 7844; - public const uint ElixirOfLesserAgility = 3160; - public const uint ElixirOfDefense = 3220; - public const uint StrongTrollsBloodElixir = 3222; - public const uint ElixirOfMinorAccuracy = 63729; - public const uint ElixirOfWisdom = 3166; - public const uint ElixirOfGianthGrowth = 8212; - public const uint ElixirOfMinorAgility = 2374; - public const uint ElixirOfMinorFortitude = 2378; - public const uint WeakTrollsBloodElixir = 3219; - public const uint ElixirOfLionsStrength = 2367; - public const uint ElixirOfMinorDefense = 673; - } - - [Script] - class spell_gen_mixology_bonus : AuraScript - { - int bonus = 0; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(MixologySpellIds.Mixology) && ValidateSpellEffect((spellInfo.Id, 0)); - } - - public override bool Load() - { - return GetCaster() != null && GetCaster().IsPlayer(); - } - - void SetBonusValueForEffect(uint effIndex, int value, AuraEffect aurEff) - { - if (aurEff.GetEffIndex() == effIndex) - bonus = value; - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster().HasAura(MixologySpellIds.Mixology) && GetCaster().HasSpell(GetEffectInfo(0).TriggerSpell)) - { - switch (GetId()) - { - case MixologySpellIds.WeakTrollsBloodElixir: - case MixologySpellIds.MagebloodElixir: - bonus = amount; + case SpellIds.ChargeTriggerTrialChampion: + spellId = SpellIds.ChargeCharging20K1; break; - case MixologySpellIds.ElixirOfFrostPower: - case MixologySpellIds.LesserFlaskOfToughness: - case MixologySpellIds.LesserFlaskOfResistance: - bonus = MathFunctions.CalculatePct(amount, 80); - break; - case MixologySpellIds.ElixirOfMinorDefense: - case MixologySpellIds.ElixirOfLionsStrength: - case MixologySpellIds.ElixirOfMinorAgility: - case MixologySpellIds.MajorTrollsBlloodElixir: - case MixologySpellIds.ElixirOfShadowPower: - case MixologySpellIds.ElixirOfBruteForce: - case MixologySpellIds.MightyTrollsBloodElixir: - case MixologySpellIds.ElixirOfGreaterFirepower: - case MixologySpellIds.OnslaughtElixir: - case MixologySpellIds.EarthenElixir: - case MixologySpellIds.ElixirOfMajorAgility: - case MixologySpellIds.FlaskOfTheTitans: - case MixologySpellIds.FlaskOfRelentlessAssault: - case MixologySpellIds.FlaskOfStoneblood: - case MixologySpellIds.ElixirOfMinorAccuracy: - bonus = MathFunctions.CalculatePct(amount, 50); - break; - case MixologySpellIds.ElixirOfProtection: - bonus = 280; - break; - case MixologySpellIds.ElixirOfMajorDefense: - bonus = 200; - break; - case MixologySpellIds.ElixirOfGreaterDefense: - case MixologySpellIds.ElixirOfSuperiorDefense: - bonus = 140; - break; - case MixologySpellIds.ElixirOfFortitude: - bonus = 100; - break; - case MixologySpellIds.FlaskOfEndlessRage: - bonus = 82; - break; - case MixologySpellIds.ElixirOfDefense: - bonus = 70; - break; - case MixologySpellIds.ElixirOfDemonslaying: - bonus = 50; - break; - case MixologySpellIds.FlaskOfTheFrostWyrm: - bonus = 47; - break; - case MixologySpellIds.WrathElixir: - bonus = 32; - break; - case MixologySpellIds.ElixirOfMajorFrostPower: - case MixologySpellIds.ElixirOfMajorFirepower: - case MixologySpellIds.ElixirOfMajorShadowPower: - bonus = 29; - break; - case MixologySpellIds.ElixirOfMightyToughts: - bonus = 27; - break; - case MixologySpellIds.FlaskOfSupremePower: - case MixologySpellIds.FlaskOfBlindingLight: - case MixologySpellIds.FlaskOfPureDeath: - case MixologySpellIds.ShadowpowerElixir: - bonus = 23; - break; - case MixologySpellIds.ElixirOfMightyAgility: - case MixologySpellIds.FlaskOfDistilledWisdom: - case MixologySpellIds.ElixirOfSpirit: - case MixologySpellIds.ElixirOfMightyStrength: - case MixologySpellIds.FlaskOfPureMojo: - case MixologySpellIds.ElixirOfAccuracy: - case MixologySpellIds.ElixirOfDeadlyStrikes: - case MixologySpellIds.ElixirOfMightyDefense: - case MixologySpellIds.ElixirOfExpertise: - case MixologySpellIds.ElixirOfArmorPiercing: - case MixologySpellIds.ElixirOfLightningSpeed: - bonus = 20; - break; - case MixologySpellIds.FlaskOfChromaticResistance: - bonus = 17; - break; - case MixologySpellIds.ElixirOfMinorFortitude: - case MixologySpellIds.ElixirOfMajorStrength: - bonus = 15; - break; - case MixologySpellIds.FlaskOfMightyRestoration: - bonus = 13; - break; - case MixologySpellIds.ArcaneElixir: - bonus = 12; - break; - case MixologySpellIds.ElixirOfGreaterAgility: - case MixologySpellIds.ElixirOfGiants: - bonus = 11; - break; - case MixologySpellIds.ElixirOfAgility: - case MixologySpellIds.ElixirOfGreaterIntellect: - case MixologySpellIds.ElixirOfSages: - case MixologySpellIds.ElixirOfIronskin: - case MixologySpellIds.ElixirOfMightyMageblood: - bonus = 10; - break; - case MixologySpellIds.ElixirOfHealingPower: - bonus = 9; - break; - case MixologySpellIds.ElixirOfDraenicWisdom: - case MixologySpellIds.GurusElixir: - bonus = 8; - break; - case MixologySpellIds.ElixirOfFirepower: - case MixologySpellIds.ElixirOfMajorMageblood: - case MixologySpellIds.ElixirOfMastery: - bonus = 6; - break; - case MixologySpellIds.ElixirOfLesserAgility: - case MixologySpellIds.ElixirOfOgresStrength: - case MixologySpellIds.ElixirOfWisdom: - case MixologySpellIds.ElixirOfTheMongoose: - bonus = 5; - break; - case MixologySpellIds.StrongTrollsBloodElixir: - case MixologySpellIds.FlaskOfChromaticWonder: - bonus = 4; - break; - case MixologySpellIds.ElixirOfEmpowerment: - bonus = -10; - break; - case MixologySpellIds.AdeptsElixir: - SetBonusValueForEffect(0, 13, aurEff); - SetBonusValueForEffect(1, 13, aurEff); - SetBonusValueForEffect(2, 8, aurEff); - break; - case MixologySpellIds.ElixirOfMightyFortitude: - SetBonusValueForEffect(0, 160, aurEff); - break; - case MixologySpellIds.ElixirOfMajorFortitude: - SetBonusValueForEffect(0, 116, aurEff); - SetBonusValueForEffect(1, 6, aurEff); - break; - case MixologySpellIds.FelStrengthElixir: - SetBonusValueForEffect(0, 40, aurEff); - SetBonusValueForEffect(1, 40, aurEff); - break; - case MixologySpellIds.FlaskOfFortification: - SetBonusValueForEffect(0, 210, aurEff); - SetBonusValueForEffect(1, 5, aurEff); - break; - case MixologySpellIds.GreaterArcaneElixir: - SetBonusValueForEffect(0, 19, aurEff); - SetBonusValueForEffect(1, 19, aurEff); - SetBonusValueForEffect(2, 5, aurEff); - break; - case MixologySpellIds.ElixirOfGianthGrowth: - SetBonusValueForEffect(0, 5, aurEff); + case SpellIds.ChargeTriggerFactionMounts: + spellId = SpellIds.ChargeChargingEffect8K5; break; default: - Log.outError(LogFilter.Spells, $"SpellId {GetId()} couldn't be processed in spell_gen_mixology_bonus"); - break; + return; } - amount += bonus; - } - } - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, SpellConst.EffectAll, AuraType.Any)); + // If target isn't a training dummy there's a chance of failing the charge + if (!target.IsCharmedOwnedByPlayerOrPlayer() && RandomHelper.randChance(12.5f)) + spellId = SpellIds.ChargeMissEffect; + + Unit vehicle = GetCaster().GetVehicleBase(); + if (vehicle != null) + vehicle.CastSpell(target, spellId, false); + else + GetCaster().CastSpell(target, spellId, false); + break; + } + case 1: // On damaging spells, for removing a defend layer + case 2: + { + var auras = target.GetAppliedAuras(); + foreach (var itr in auras) + { + Aura aura = itr.Value.GetBase(); + if (aura != null) + { + if (aura.GetId() == 62552 || aura.GetId() == 62719 || aura.GetId() == 64100 || aura.GetId() == 66482) + { + aura.ModStackAmount(-1, AuraRemoveMode.EnemySpell); + // Remove dummys from rider (Necessary for updating visual shields) + Unit rider = target.GetCharmer(); + if (rider != null) + { + Aura defend = rider.GetAura(aura.GetId()); + if (defend != null) + defend.ModStackAmount(-1, AuraRemoveMode.EnemySpell); + } + break; + } + } + } + break; + } + default: + break; } } - [Script] - class spell_gen_landmine_knockback_achievement : SpellScript + void HandleChargeEffect(uint effIndex) { - const uint SpellLandmineKnockbackAchievement = 57064; + uint spellId; - void HandleScript(uint effIndex) + switch (GetSpellInfo().Id) { - Player target = GetHitPlayer(); - if (target != null) - { - Aura aura = GetHitAura(); - if (aura == null || aura.GetStackAmount() < 10) + case SpellIds.ChargeChargingEffect8K5: + spellId = SpellIds.ChargeDamage8K5; + break; + case SpellIds.ChargeCharging20K1: + case SpellIds.ChargeCharging20K2: + spellId = SpellIds.ChargeDamage20K; + break; + case SpellIds.ChargeChargingEffect45K1: + case SpellIds.ChargeChargingEffect45K2: + spellId = SpellIds.ChargeDamage45K; + break; + default: + return; + } + + Unit rider = GetCaster().GetCharmer(); + if (rider != null) + rider.CastSpell(GetHitUnit(), spellId, false); + else + GetCaster().CastSpell(GetHitUnit(), spellId, false); + } + + public override void Register() + { + SpellInfo spell = Global.SpellMgr.GetSpellInfo(m_scriptSpellId, Difficulty.None); + + if (spell.HasEffect(SpellEffectName.ScriptEffect)) + OnEffectHitTarget.Add(new(HandleScriptEffect, SpellConst.EffectFirstFound, SpellEffectName.ScriptEffect)); + + if (spell.GetEffect(0).IsEffect(SpellEffectName.Charge)) + OnEffectHitTarget.Add(new(HandleChargeEffect, 0, SpellEffectName.Charge)); + } +} + +// 6870 Moss Covered Feet +[Script] // 31399 Moss Covered Feet +class spell_gen_moss_covered_feet : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FallDown); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + eventInfo.GetActionTarget().CastSpell(null, SpellIds.FallDown, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 28702 - Netherbloom +class spell_gen_netherbloom : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + for (byte i = 0; i < 5; ++i) + if (!ValidateSpellInfo(SpellIds.NetherbloomPollen1 + i)) + return false; + + return true; + } + + void HandleScript(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + + Unit target = GetHitUnit(); + if (target != null) + { + // 25% chance of casting a random buff + if (RandomHelper.randChance(75)) + return; + + // triggered spells are 28703 to 28707 + // Note: some sources say, that there was the possibility of + // receiving a debuff. However, this seems to be removed by a patch. + + // don't overwrite an existing aura + for (byte i = 0; i < 5; ++i) + if (target.HasAura(SpellIds.NetherbloomPollen1 + i)) return; - target.CastSpell(target, SpellLandmineKnockbackAchievement, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + target.CastSpell(target, SpellIds.NetherbloomPollen1 + RandomHelper.URand(0, 4), true); } } - [Script] // 34098 - ClearAllDebuffs - class spell_gen_clear_debuffs : SpellScript + public override void Register() { - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - { - target.RemoveOwnedAuras(aura => - { - SpellInfo spellInfo = aura.GetSpellInfo(); - return spellInfo.IsPositive() && spellInfo.IsPassive(); - }); + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} - } - } +[Script] // 28720 - Nightmare Vine +class spell_gen_nightmare_vine : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NightmarePollen); + } - public override void Register() + void HandleScript(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + + Unit target = GetHitUnit(); + if (target != null) { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + // 25% chance of casting Nightmare Pollen + if (RandomHelper.randChance(25)) + target.CastSpell(target, SpellIds.NightmarePollen, true); } } - [Script] - class spell_gen_pony_mount_check : AuraScript + public override void Register() { - const uint AchievPonyUp = 3736; - const uint MountPony = 29736; + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} - void HandleEffectPeriodic(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster == null) - return; - Player owner = caster.GetOwner().ToPlayer(); - if (owner == null || !owner.HasAchieved(AchievPonyUp)) - return; +[Script] // 27746 - Nitrous Boost +class spell_gen_nitrous_boost : AuraScript +{ + void PeriodicTick(AuraEffect aurEff) + { + PreventDefaultAction(); - if (owner.IsMounted()) - { - caster.Mount(MountPony); - caster.SetSpeedRate(UnitMoveType.Run, owner.GetSpeedRate(UnitMoveType.Run)); - } - else if (caster.IsMounted()) - { - caster.Dismount(); - caster.SetSpeedRate(UnitMoveType.Run, owner.GetSpeedRate(UnitMoveType.Run)); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } + if (GetCaster() != null && GetTarget().GetPower(PowerType.Mana) >= 10) + GetTarget().ModifyPower(PowerType.Mana, -10); + else + Remove(); } - struct CorruptinPlagueIds + public override void Register() { - public const uint NpcApexisFlayer = 22175; - public const uint NpcShardHideBoar = 22180; - public const uint NpcAetherRay = 22181; - public const uint SpellCorruptingPlague = 40350; + OnEffectPeriodic.Add(new(PeriodicTick, 1, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 27539 - Obsidian Armor +class spell_gen_obsidian_armor : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GenObsidianArmorHoly, SpellIds.GenObsidianArmorFire, SpellIds.GenObsidianArmorNature, SpellIds.GenObsidianArmorFrost, SpellIds.GenObsidianArmorShadow, SpellIds.GenObsidianArmorArcane); } - // 40350 - Corrupting Plague - class CorruptingPlagueSearcher : ICheck + bool CheckProc(ProcEventInfo eventInfo) { - Unit _unit; - float _distance; - - public CorruptingPlagueSearcher(Unit obj, float distance) - { - _unit = obj; - _distance = distance; - } - - public bool Invoke(Unit u) - { - if (_unit.GetDistance2d(u) < _distance && - (u.GetEntry() == CorruptinPlagueIds.NpcApexisFlayer || u.GetEntry() == CorruptinPlagueIds.NpcShardHideBoar || u.GetEntry() == CorruptinPlagueIds.NpcAetherRay) && - !u.HasAura(CorruptinPlagueIds.SpellCorruptingPlague)) - return true; - + if (eventInfo.GetSpellInfo() == null) return false; - } - } - - [Script] // 40349 - Corrupting Plague - class spell_corrupting_plague_AuraScript : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(CorruptinPlagueIds.SpellCorruptingPlague); - } - - void OnPeriodic(AuraEffect aurEff) - { - Unit owner = GetTarget(); - - List targets = new(); - CorruptingPlagueSearcher creature_check = new(owner, 15.0f); - CreatureListSearcher creature_searcher = new(owner, targets, creature_check); - Cell.VisitGridObjects(owner, creature_searcher, 15.0f); - - if (!targets.Empty()) - return; - - PreventDefaultAction(); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicTriggerSpell)); - } - } - - struct StasisFieldIds - { - public const uint NpcDaggertailLizard = 22255; - public const uint SpellStasisField = 40307; - } - - // 40307 - Stasis Field - class StasisFieldSearcher : ICheck - { - Unit _unit; - float _distance; - - public StasisFieldSearcher(Unit obj, float distance) - { - _unit = obj; - _distance = distance; - } - - public bool Invoke(Unit u) - { - if (_unit.GetDistance2d(u) < _distance && - (u.GetEntry() == CorruptinPlagueIds.NpcApexisFlayer || u.GetEntry() == CorruptinPlagueIds.NpcShardHideBoar || u.GetEntry() == CorruptinPlagueIds.NpcAetherRay || u.GetEntry() == StasisFieldIds.NpcDaggertailLizard) && - !u.HasAura(StasisFieldIds.SpellStasisField)) - return true; + if (SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask()) == SpellSchools.Normal) return false; - } + + return true; } - [Script] // 40306 - Stasis Field - class spell_stasis_field_AuraScript : AuraScript + void OnProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + PreventDefaultAction(); + + uint spellId = 0; + switch (SharedConst.GetFirstSchoolInMask(eventInfo.GetSchoolMask())) { - return ValidateSpellInfo(StasisFieldIds.SpellStasisField); - } - - void OnPeriodic(AuraEffect aurEff) - { - Unit owner = GetTarget(); - - List targets = new(); - StasisFieldSearcher creature_check = new(owner, 15.0f); - CreatureListSearcher creature_searcher = new(owner, targets, creature_check); - Cell.VisitGridObjects(owner, creature_searcher, 15.0f); - - if (!targets.Empty()) + case SpellSchools.Holy: + spellId = SpellIds.GenObsidianArmorHoly; + break; + case SpellSchools.Fire: + spellId = SpellIds.GenObsidianArmorFire; + break; + case SpellSchools.Nature: + spellId = SpellIds.GenObsidianArmorNature; + break; + case SpellSchools.Frost: + spellId = SpellIds.GenObsidianArmorFrost; + break; + case SpellSchools.Shadow: + spellId = SpellIds.GenObsidianArmorShadow; + break; + case SpellSchools.Arcane: + spellId = SpellIds.GenObsidianArmorArcane; + break; + default: return; - - PreventDefaultAction(); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicTriggerSpell)); } + GetTarget().CastSpell(GetTarget(), spellId, aurEff); } - [Script] - class spell_gen_vehicle_control_link : AuraScript + public override void Register() { - const uint SpellSiegeTankControl = 47963; + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(OnProc, 0, AuraType.Dummy)); + } +} - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellSiegeTankControl); //aurEff.GetAmount() - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - } +[Script] +class spell_gen_oracle_wolvar_reputation : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); } - [Script] // 34779 - Freezing Circle - class spell_freezing_circle : SpellScript + public override bool Load() { - const uint SpellFreezingCirclePitOfSaronNormal = 69574; - const uint SpellFreezingCirclePitOfSaronHeroic = 70276; - const uint SpellFreezingCircle = 34787; - const uint SpellFreezingCircleScenario = 141383; - const uint MapIdBloodInTheSnowScenario = 1130; + return GetCaster().IsPlayer(); + } - public override bool Validate(SpellInfo spellInfo) + void HandleDummy(uint effIndex) + { + Player player = GetCaster().ToPlayer(); + uint factionId = (uint)GetEffectInfo().CalcValue(); + int repChange = GetEffectInfo(1).CalcValue(); + + var factionEntry = CliDB.FactionStorage.LookupByKey(factionId); + if (factionEntry == null) + return; + + // Set rep to baserep + basepoints (expecting spillover for oposite faction . become hated) + // Not when player already has equal or higher rep with this faction + if (player.GetReputationMgr().GetReputation(factionEntry) < repChange) + player.GetReputationMgr().SetReputation(factionEntry, repChange); + + // EffectIndex2 most likely update at war state, we already handle this in SetReputation + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_gen_orc_disguise : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.OrcDisguiseTrigger, SpellIds.OrcDisguiseMale, SpellIds.OrcDisguiseFemale); + } + + void HandleScript(uint effIndex) + { + Unit caster = GetCaster(); + Player target = GetHitPlayer(); + if (target != null) { - return ValidateSpellInfo(SpellFreezingCirclePitOfSaronNormal, - SpellFreezingCirclePitOfSaronHeroic, - SpellFreezingCircle, - SpellFreezingCircleScenario - ); - } - - void HandleDamage(uint effIndex) - { - Unit caster = GetCaster(); - uint spellId; - Map map = caster.GetMap(); - - if (map.IsDungeon()) - spellId = map.IsHeroic() ? SpellFreezingCirclePitOfSaronHeroic : SpellFreezingCirclePitOfSaronNormal; + var gender = target.GetNativeGender(); + if (gender == 0) + caster.CastSpell(target, SpellIds.OrcDisguiseMale, true); else - spellId = map.GetId() == MapIdBloodInTheSnowScenario ? SpellFreezingCircleScenario : SpellFreezingCircle; - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(spellId, GetCastDifficulty()); - if (spellInfo != null && spellInfo.GetEffects().Empty()) - SetHitDamage(spellInfo.GetEffect(0).CalcValue()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDamage, 1, SpellEffectName.SchoolDamage)); + caster.CastSpell(target, SpellIds.OrcDisguiseFemale, true); } } - [Script] // Used for some spells cast by vehicles or charmed creatures that do not send a cooldown event on their own - class spell_gen_charmed_unit_spell_cooldown : SpellScript + public override void Register() { - void HandleCast() + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 35201 - Paralytic Poison +class spell_gen_paralytic_poison : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Paralysis); + } + + void HandleStun(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + GetTarget().CastSpell(null, SpellIds.Paralysis, aurEff); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleStun, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); + } +} + +[Script] +class spell_gen_prevent_emotes : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetUnitFlag(UnitFlags.PreventEmotesFromChatText); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveUnitFlag(UnitFlags.PreventEmotesFromChatText); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, SpellConst.EffectFirstFound, AuraType.Any, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, SpellConst.EffectFirstFound, AuraType.Any, AuraEffectHandleModes.Real)); + } +} + +[Script] +class spell_gen_player_say : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return CliDB.BroadcastTextStorage.HasRecord((uint)spellInfo.GetEffect(0).CalcValue()); + } + + void HandleScript(uint effIndex) + { + // Note: target here is always player; caster here is gameobject, creature or player (self cast) + Unit target = GetHitUnit(); + if (target != null) + target.Say((uint)GetEffectValue(), target); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script("spell_item_soul_harvesters_charm")] +[Script("spell_item_commendation_of_kaelthas")] +[Script("spell_item_corpse_tongue_coin")] +[Script("spell_item_corpse_tongue_coin_heroic")] +[Script("spell_item_petrified_twilight_scale")] +[Script("spell_item_petrified_twilight_scale_heroic")] +class spell_gen_proc_below_pct_damaged : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) + { + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return false; + + int pct = GetSpellInfo().GetEffect(0).CalcValue(); + + if (eventInfo.GetActionTarget().HealthBelowPctDamaged(pct, damageInfo.GetDamage())) + return true; + + return false; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] +class spell_gen_proc_charge_drop_only : AuraScript +{ + void HandleChargeDrop(ProcEventInfo eventInfo) + { + PreventDefaultAction(); + } + + public override void Register() + { + OnProc.Add(new(HandleChargeDrop)); + } +} + +[Script] // 45472 Parachute +class spell_gen_parachute : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Parachute, SpellIds.ParachuteBuff); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + Player target = GetTarget().ToPlayer(); + if (target != null && target.IsFalling()) { - Unit caster = GetCaster(); - Player owner = caster.GetCharmerOrOwnerPlayerOrPlayerItself(); - if (owner != null) + target.RemoveAurasDueToSpell(SpellIds.Parachute); + target.CastSpell(target, SpellIds.ParachuteBuff, true); + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] +class spell_gen_pet_summoned : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + Player player = GetCaster().ToPlayer(); + if (player.GetLastPetNumber() != 0) + { + PetType newPetType = (player.GetClass() == Class.Hunter) ? PetType.Hunter : PetType.Summon; + Pet newPet = new Pet(player, newPetType); + if (newPet.LoadPetFromDB(player, 0, player.GetLastPetNumber(), true)) { - SpellCooldownPkt spellCooldown = new(); - spellCooldown.Caster = owner.GetGUID(); - spellCooldown.Flags = SpellCooldownFlags.None; - spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(GetSpellInfo().Id, GetSpellInfo().RecoveryTime)); - owner.SendPacket(spellCooldown); + // revive the pet if it is dead + if (newPet.GetDeathState() != DeathState.Alive && newPet.GetDeathState() != DeathState.JustRespawned) + newPet.SetDeathState(DeathState.JustRespawned); + + newPet.SetFullHealth(); + newPet.SetFullPower(newPet.GetPowerType()); + + switch (newPet.GetEntry()) + { + case CreatureIds.Doomguard: + case CreatureIds.Infernal: + newPet.SetEntry(CreatureIds.Imp); + break; + default: + break; + } + } + else + newPet.Dispose(); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 36553 - PetWait +class spell_gen_pet_wait : SpellScript +{ + void HandleScript(uint effIndex) + { + GetCaster().GetMotionMaster().Clear(); + GetCaster().GetMotionMaster().MoveIdle(); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_profession_research : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + SpellCastResult CheckRequirement() + { + Player player = GetCaster().ToPlayer(); + + if (SkillDiscovery.HasDiscoveredAllSpells(GetSpellInfo().Id, player)) + { + SetCustomCastResultMessage(SpellCustomErrors.NothingToDiscover); + return SpellCastResult.CustomError; + } + + return SpellCastResult.SpellCastOk; + } + + void HandleScript(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + uint spellId = GetSpellInfo().Id; + + // Learn random explicit discovery recipe (if any) + // Players will now learn 3 recipes the very first time they perform Northrend Inscription Research (3.3.0 patch notes) + if (spellId == SpellIds.NorthrendInscriptionResearch && !SkillDiscovery.HasDiscoveredAnySpell(spellId, caster)) + { + for (int i = 0; i < 2; ++i) + { + uint discoveredSpellId1 = SkillDiscovery.GetExplicitDiscoverySpell(spellId, caster); + if (discoveredSpellId1 != 0) + caster.LearnSpell(discoveredSpellId1, false); } } - public override void Register() + uint discoveredSpellId = SkillDiscovery.GetExplicitDiscoverySpell(spellId, caster); + if (discoveredSpellId != 0) + caster.LearnSpell(discoveredSpellId, false); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckRequirement)); + OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_pvp_trinket : SpellScript +{ + void TriggerAnimation() + { + Player caster = GetCaster().ToPlayer(); + + switch (caster.GetEffectiveTeam()) { - OnCast.Add(new(HandleCast)); + case Team.Alliance: + caster.CastSpell(caster, SpellIds.PvpTrinketAlliance, TriggerCastFlags.FullMask); + break; + case Team.Horde: + caster.CastSpell(caster, SpellIds.PvpTrinketHorde, TriggerCastFlags.FullMask); + break; + default: + break; } } - [Script] - class spell_gen_cannon_blast : SpellScript + public override void Register() { - const uint SpellCannonBlast = 42578; - const uint SpellCannonBlastDamage = 42576; + AfterCast.Add(new(TriggerAnimation)); + } +} - public override bool Validate(SpellInfo spellInfo) +[Script] +class spell_gen_remove_flight_auras : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) { - return ValidateSpellInfo(SpellCannonBlast); - } - void HandleScript(uint effIndex) - { - int bp = GetEffectValue(); - Unit target = GetHitUnit(); - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, bp); - target.CastSpell(target, SpellCannonBlastDamage, args); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + target.RemoveAurasByType(AuraType.Fly); + target.RemoveAurasByType(AuraType.ModIncreaseMountedFlightSpeed); } } - [Script] // 37751 - Submerged - class spell_gen_submerged : SpellScript + public override void Register() { - void HandleScript(uint eff) - { - Creature target = GetHitCreature(); - if (target != null) - target.SetStandState(UnitStandStateType.Submerged); - } + OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); + } +} - public override void Register() +[Script] // 20589 - Escape artist +class spell_gen_remove_impairing_auras : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + GetHitUnit().RemoveMovementImpairingAuras(true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +// 23493 - Restoration +[Script] // 24379 - Restoration +class spell_gen_restoration : AuraScript +{ + void PeriodicTick(AuraEffect aurEff) + { + PreventDefaultAction(); + + Unit target = GetTarget(); + if (target == null) + return; + + uint heal = (uint)target.CountPctFromMaxHealth(10); + HealInfo healInfo = new(target, target, heal, GetSpellInfo(), GetSpellInfo().GetSchoolMask()); + target.HealBySpell(healInfo); + + /// @todo: should proc other auras? + int mana = target.GetMaxPower(PowerType.Mana); + if (mana != 0) { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + mana /= 10; + target.EnergizeBySpell(target, GetSpellInfo(), mana, PowerType.Mana); } } - [Script] // 169869 - Transformation Sickness - class spell_gen_decimatus_transformation_sickness : SpellScript + public override void Register() { - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - target.SetHealth(target.CountPctFromMaxHealth(25)); - } + OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicTriggerSpell)); + } +} - public override void Register() +// 38772 Grievous Wound +// 43937 Grievous Wound +// 62331 Impale +[Script] // 62418 Impale +class spell_gen_remove_on_health_pct : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void PeriodicTick(AuraEffect aurEff) + { + // they apply damage so no need to check for ticks here + + if (GetTarget().HealthAbovePct(GetEffectInfo(1).CalcValue())) { - OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); + Remove(AuraRemoveMode.EnemySpell); + PreventDefaultAction(); } } - [Script] // 189491 - Summon Towering Infernal. - class spell_gen_anetheron_summon_towering_infernal : SpellScript + public override void Register() { - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); - } + OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicDamage)); + } +} - public override void Register() +// 31956 Grievous Wound +// 38801 Grievous Wound +// 43093 Grievous Throw +// 58517 Grievous Wound +[Script] // 59262 Grievous Wound +class spell_gen_remove_on_full_health : AuraScript +{ + void PeriodicTick(AuraEffect aurEff) + { + // if it has only periodic effect, allow 1 tick + bool onlyEffect = GetSpellInfo().GetEffects().Count == 1; + if (onlyEffect && aurEff.GetTickNumber() <= 1) + return; + + if (GetTarget().IsFullHealth()) { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + Remove(AuraRemoveMode.EnemySpell); + PreventDefaultAction(); } } - [Script] - class spell_gen_mark_of_kazrogal_hellfire : SpellScript + public override void Register() { - void FilterTargets(List targets) + OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicDamage)); + } +} + +// 70292 - Glacial Strike +[Script] // 71316 - Glacial Strike +class spell_gen_remove_on_full_health_pct : AuraScript +{ + void PeriodicTick(AuraEffect aurEff) + { + // they apply damage so no need to check for ticks here + + if (GetTarget().IsFullHealth()) { - targets.RemoveAll(target => + Remove(AuraRemoveMode.EnemySpell); + PreventDefaultAction(); + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(PeriodicTick, 2, AuraType.PeriodicDamagePercent)); + } +} + +class ReplenishmentCheck +{ + public bool Invoke(WorldObject obj) + { + Unit target = obj.ToUnit(); + if (target != null) + return target.GetPowerType() != PowerType.Mana; + + return true; + } +} + +[Script] +class spell_gen_replenishment : SpellScript +{ + void RemoveInvalidTargets(List targets) + { + // In arenas Replenishment may only affect the caster + Player caster = GetCaster().ToPlayer(); + if (caster != null) + { + if (caster.InArena()) { - Unit unit = target.ToUnit(); - if (unit != null) - return unit.GetPowerType() != PowerType.Mana; - return false; - }); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaEnemy)); - } - } - - [Script] - class spell_gen_mark_of_kazrogal_hellfire_AuraScript : AuraScript - { - const uint SpellMarkOfKazrogalHellfire = 189512; - const uint SpellMarkOfKazrogalDamageHellfire = 189515; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellMarkOfKazrogalDamageHellfire); - } - - void OnPeriodic(AuraEffect aurEff) - { - Unit target = GetTarget(); - - if (target.GetPower(PowerType.Mana) == 0) - { - target.CastSpell(target, SpellMarkOfKazrogalDamageHellfire, aurEff); - // Remove aura - SetDuration(0); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PowerBurn)); - } - } - - [Script] - class spell_gen_azgalor_rain_of_fire_hellfire_citadel : SpellScript - { - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 99947 - Face Rage - class spell_gen_face_rage : AuraScript - { - const uint SpellFaceRage = 99947; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFaceRage) - && ValidateSpellEffect((spellInfo.Id, 2)); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(GetEffectInfo(2).TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); - } - } - - [Script] // 187213 - Impatient Mind - class spell_gen_impatient_mind : AuraScript - { - const uint SpellImpatientMind = 187213; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellImpatientMind); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - [Script] // 209352 - Boost 2.0 [Paladin+Priest] - Watch for Shield - class spell_gen_boost_2_0_paladin_priest_watch_for_shield : AuraScript - { - uint SpellPowerWordShield = 17; - uint SpellDivineShield = 642; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellPowerWordShield, SpellDivineShield); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - SpellInfo spellInfo = procInfo.GetSpellInfo(); - return spellInfo != null && (spellInfo.Id == SpellPowerWordShield || spellInfo.Id == SpellDivineShield); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } - } - - // 269083 - Enlisted - [Script] // 282559 - Enlisted - class spell_gen_war_mode_enlisted : AuraScript - { - void CalcWarModeBonus(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player target = GetUnitOwner().ToPlayer(); - if (target == null) + targets.Clear(); + targets.Add(caster); return; + } + } - switch (target.GetTeamId()) + targets.RemoveAll(new ReplenishmentCheck().Invoke); + + byte maxTargets = 10; + + if (targets.Count > maxTargets) + { + targets.Sort(new PowerPctOrderPred(PowerType.Mana)); + targets.Resize(maxTargets); + } + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(RemoveInvalidTargets, SpellConst.EffectAll, Targets.UnitCasterAreaRaid)); + } +} + +[Script] +class spell_gen_replenishment_aura : AuraScript +{ + public override bool Load() + { + return GetUnitOwner().GetPowerType() == PowerType.Mana; + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + switch (GetSpellInfo().Id) + { + case SpellIds.Replenishment: + amount = (int)(GetUnitOwner().GetMaxPower(PowerType.Mana) * 0.002f); + break; + case SpellIds.InfiniteReplenishment: + amount = (int)(GetUnitOwner().GetMaxPower(PowerType.Mana) * 0.0025f); + break; + default: + break; + } + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.PeriodicEnergize)); + } +} + +[Script] +class spell_gen_running_wild : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AlteredForm); + } + + public override void OnPrecast() + { + GetCaster().CastSpell(GetCaster(), SpellIds.AlteredForm, TriggerCastFlags.FullMask); + } + + public override void Register() + { + } +} + +[Script] +class spell_gen_running_wild_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (!CliDB.CreatureDisplayInfoStorage.ContainsKey(SharedConst.DisplayIdHiddenMount)) + return false; + return true; + } + + void HandleMount(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + PreventDefaultAction(); + + target.Mount(SharedConst.DisplayIdHiddenMount, 0, 0); + + // cast speed aura + var mountCapability = CliDB.MountCapabilityStorage.LookupByKey(aurEff.GetAmount()); + if (mountCapability != null) + target.CastSpell(target, mountCapability.ModSpellAuraID, TriggerCastFlags.FullMask); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleMount, 1, AuraType.Mounted, AuraEffectHandleModes.Real)); + } +} + +[Script] +class spell_gen_two_forms : SpellScript +{ + SpellCastResult CheckCast() + { + if (GetCaster().IsInCombat()) + { + SetCustomCastResultMessage(SpellCustomErrors.CantTransform); + return SpellCastResult.CustomError; + } + + // Player cannot transform to human form if he is forced to be worgen for some reason (Darkflight) + var alteredFormAuras = GetCaster().GetAuraEffectsByType(AuraType.WorgenAlteredForm); + if (alteredFormAuras.Count > 1) + { + SetCustomCastResultMessage(SpellCustomErrors.CantTransform); + return SpellCastResult.CustomError; + } + + return SpellCastResult.SpellCastOk; + } + + void HandleTransform(uint effIndex) + { + Unit target = GetHitUnit(); + PreventHitDefaultEffect(effIndex); + if (target.HasAuraType(AuraType.WorgenAlteredForm)) + target.RemoveAurasByType(AuraType.WorgenAlteredForm); + else // Basepoints 1 for this aura control whether to trigger transform transition animation or not. + target.CastSpell(target, SpellIds.AlteredForm, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, 1)); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(HandleTransform, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_gen_darkflight : SpellScript +{ + void TriggerTransform() + { + GetCaster().CastSpell(GetCaster(), SpellIds.AlteredForm, TriggerCastFlags.FullMask); + } + + public override void Register() + { + AfterCast.Add(new(TriggerTransform)); + } +} + +[Script] +class spell_gen_seaforium_blast : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PlantChargesCreditAchievement); + } + + public override bool Load() + { + return GetGObjCaster().GetOwnerGUID().IsPlayer(); + } + + void AchievementCredit(uint effIndex) + { + Unit owner = GetGObjCaster().GetOwner(); + if (owner != null) + { + GameObject go = GetHitGObj(); + if (go != null && go.GetGoInfo().type == GameObjectTypes.DestructibleBuilding) + owner.CastSpell(null, SpellIds.PlantChargesCreditAchievement, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(AchievementCredit, 1, SpellEffectName.GameObjectDamage)); + } +} + +[Script] +class spell_gen_spectator_cheer_trigger : SpellScript +{ + static Emote[] EmoteArray = [Emote.OneshotCheer, Emote.OneshotExclamation, Emote.OneshotApplaud]; + + void HandleDummy(uint effIndex) + { + if (RandomHelper.randChance(40)) + GetCaster().HandleEmoteCommand(EmoteArray.SelectRandom()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_gen_spirit_healer_res : SpellScript +{ + public override bool Load() + { + return GetOriginalCaster() != null && GetOriginalCaster().IsPlayer(); + } + + void HandleDummy(uint effIndex) + { + Player originalCaster = GetOriginalCaster().ToPlayer(); + Unit target = GetHitUnit(); + if (target != null) + { + NPCInteractionOpenResult spiritHealerConfirm = new(); + spiritHealerConfirm.Npc = target.GetGUID(); + spiritHealerConfirm.InteractionType = PlayerInteractionType.SpiritHealer; + spiritHealerConfirm.Success = true; + originalCaster.SendPacket(spiritHealerConfirm); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_gen_summon_tournament_mount : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LanceEquipped); + } + + SpellCastResult CheckIfLanceEquiped() + { + if (GetCaster().IsInDisallowedMountForm()) + GetCaster().RemoveAurasByType(AuraType.ModShapeshift); + + if (!GetCaster().HasAura(SpellIds.LanceEquipped)) + { + SetCustomCastResultMessage(SpellCustomErrors.MustHaveLanceEquipped); + return SpellCastResult.CustomError; + } + + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckIfLanceEquiped)); + } +} + +[Script] // 41213, 43416, 69222, 73076 - Throw Shield +class spell_gen_throw_shield : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_tournament_duel : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.OnTournamentMount, SpellIds.MountedDuel); + } + + void HandleScriptEffect(uint effIndex) + { + Unit rider = GetCaster().GetCharmer(); + if (rider != null) + { + Player playerTarget = GetHitPlayer(); + if (playerTarget != null && playerTarget.HasAura(SpellIds.OnTournamentMount) && playerTarget.GetVehicleBase() != null) + rider.CastSpell(playerTarget, SpellIds.MountedDuel, true); + else { - case BattleGroundTeamId.Alliance: - amount = WorldStateMgr.GetValue(WorldStates.WarModeAllianceBuffValue, target.GetMap()); + Unit unitTarget = GetHitUnit(); + if (unitTarget != null && unitTarget.GetCharmer() != null && unitTarget.GetCharmer().IsPlayer() && unitTarget.GetCharmer().HasAura(SpellIds.OnTournamentMount)) + rider.CastSpell(unitTarget.GetCharmer(), SpellIds.MountedDuel, true); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_tournament_pennant : AuraScript +{ + public override bool Load() + { + return GetCaster() != null && GetCaster().IsPlayer(); + } + + void HandleApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null && caster.GetVehicleBase() == null) + caster.RemoveAurasDueToSpell(GetId()); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleApplyEffect, 0, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +[Script] +class spell_gen_teleporting : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + if (!target.IsPlayer()) + return; + + // return from top + if (target.ToPlayer().GetAreaId() == MiscConst.AreaVioletCitadelSpire) + target.CastSpell(target, SpellIds.TeleportSpireDown, true); + // teleport atop + else + target.CastSpell(target, SpellIds.TeleportSpireUp, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_trigger_exclude_caster_aura_spell : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(spellInfo.ExcludeCasterAuraSpell); + } + + void HandleTrigger() + { + // Blizz seems to just apply aura without bothering to cast + GetCaster().AddAura(GetSpellInfo().ExcludeCasterAuraSpell, GetCaster()); + } + + public override void Register() + { + AfterCast.Add(new(HandleTrigger)); + } +} + +[Script] +class spell_gen_trigger_exclude_target_aura_spell : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(spellInfo.ExcludeTargetAuraSpell); + } + + void HandleTrigger() + { + Unit target = GetHitUnit(); + if (target != null) + // Blizz seems to just apply aura without bothering to cast + GetCaster().AddAura(GetSpellInfo().ExcludeTargetAuraSpell, target); + } + + public override void Register() + { + AfterHit.Add(new(HandleTrigger)); + } +} + +[Script("spell_pvp_trinket_shared_cd", SpellIds.WillOfTheForsakenCooldownTrigger)] +[Script("spell_wotf_shared_cd", SpellIds.WillOfTheForsakenCooldownTriggerWotf)] +class spell_pvp_trinket_wotf_shared_cd(uint triggeredSpellId) : SpellScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(triggeredSpellId); + } + + void HandleScript() + { + /* + * @workaround: PendingCast flag normally means 'triggered' spell, however + * if the spell is cast triggered, the core won't send SmsgSpellGo packet + * so client never registers the cooldown (see Spell::IsNeedSendToClient) + * + * ServerToClient: SmsgSpellGo (0x0132) Length: 42 ConnIdx: 0 Time: 07/19/2010 02:32:35.000 Number: 362675 + * Caster Guid: Full: Player + * Caster Unit Guid: Full: Player + * Cast Count: 0 + * Spell Id: 72752 (72752) + * Cast Flags: PendingCast, Unknown3, Unknown7 (265) + * Time: 3901468825 + * Hit Count: 1 + * [0] Hit Guid: Player + * Miss Count: 0 + * Target Flags: Unit (2) + * Target Guid: 0x0 + */ + + // Spell flags need further research, until then just cast not triggered + GetCaster().CastSpell(null, triggeredSpellId, false); + } + + public override void Register() + { + AfterCast.Add(new(HandleScript)); + } +} + +[Script] +class spell_gen_turkey_marker : AuraScript +{ + List _applyTimes = new(); + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // store stack apply times, so we can pop them while they expire + _applyTimes.Add(GameTime.GetGameTimeMS()); + Unit target = GetTarget(); + + // on stack 15 cast the achievement crediting spell + if (GetStackAmount() >= 15) + target.CastSpell(target, SpellIds.TurkeyVengeance, new CastSpellExtraArgs(aurEff) + .SetOriginalCaster(GetCasterGUID())); + } + + void OnPeriodic(AuraEffect aurEff) + { + int removeCount = 0; + + // pop expired times off of the stack + while (!_applyTimes.Empty() && _applyTimes.First() + GetMaxDuration() < GameTime.GetGameTimeMS()) + { + _applyTimes.RemoveAt(0); + removeCount++; + } + + if (removeCount != 0) + ModStackAmount(-removeCount, AuraRemoveMode.Expire); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] +class spell_gen_upper_deck_create_foam_sword : SpellScript +{ + static uint[] itemId = [MiscConst.ItemFoamSwordGreen, MiscConst.ItemFoamSwordPink, MiscConst.ItemFoamSwordBlue, MiscConst.ItemFoamSwordRed, MiscConst.ItemFoamSwordYellow]; + + void HandleScript(uint effIndex) + { + Player player = GetHitPlayer(); + if (player != null) + { + // player can only have one of these items + for (byte i = 0; i < 5; ++i) + { + if (player.HasItemCount(itemId[i], 1, true)) + return; + } + + CreateItem(itemId[RandomHelper.IRand(0, 4)], ItemContext.None); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +// 52723 - Vampiric Touch +[Script] // 60501 - Vampiric Touch +class spell_gen_vampiric_touch : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VampiricTouchHeal); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + Unit caster = eventInfo.GetActor(); + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)(damageInfo.GetDamage() / 2)); + caster.CastSpell(caster, SpellIds.VampiricTouchHeal, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] +class spell_gen_vehicle_scaling : AuraScript +{ + public override bool Load() + { + return GetCaster() != null && GetCaster().IsPlayer(); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Unit caster = GetCaster(); + float factor; + ushort baseItemLevel; + + /// @todo Reserach coeffs for different vehicles + switch (GetId()) + { + case SpellIds.GearScaling: + factor = 1.0f; + baseItemLevel = 205; + break; + default: + factor = 1.0f; + baseItemLevel = 170; + break; + } + + float avgILvl = caster.ToPlayer().GetAverageItemLevel(); + if (avgILvl < baseItemLevel) + return; /// @todo Research possibility of scaling down + + amount = (ushort)((avgILvl - baseItemLevel) * factor); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModHealingPct)); + DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ModDamagePercentDone)); + DoEffectCalcAmount.Add(new(CalculateAmount, 2, AuraType.ModIncreaseHealthPercent)); + } +} + +[Script] +class spell_gen_vendor_bark_trigger : SpellScript +{ + void HandleDummy(uint effIndex) + { + Creature vendor = GetCaster().ToCreature(); + if (vendor != null && vendor.GetEntry() == CreatureIds.AmphitheaterVendor) + vendor.GetAI().Talk(MiscConst.SayAmphitheaterVendor); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_gen_wg_water : SpellScript +{ + SpellCastResult CheckCast() + { + if (!GetSpellInfo().CheckTargetCreatureType(GetCaster())) + return SpellCastResult.DontReport; + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + } +} + +[Script] +class spell_gen_whisper_gulch_yogg_saron_whisper : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.YoggSaronWhisperDummy); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + PreventDefaultAction(); + GetTarget().CastSpell(null, SpellIds.YoggSaronWhisperDummy, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] +class spell_gen_whisper_to_controller : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return CliDB.BroadcastTextStorage.HasRecord((uint)spellInfo.GetEffect(0).CalcValue()); + } + + void HandleScript(uint effIndex) + { + TempSummon casterSummon = GetCaster().ToTempSummon(); + if (casterSummon != null) + { + Player target = casterSummon.GetSummonerUnit().ToPlayer(); + if (target != null) + casterSummon.Whisper((uint)GetEffectValue(), target, false); + } + } + + public override void Register() + { + OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +// BasePoints of spells is Id of npc_text used to group texts, it's not implemented so texts are grouped the old way +// 50037 - Mystery of the Infinite: Future You's Whisper to Controller - Random +// 50287 - Azure Dragon: On Death Force Cast Wyrmrest Defender to Whisper to Controller - Random +// 60709 - Moti, Redux: Past You's Whisper to Controller - Random +[Script("spell_future_you_whisper_to_controller_random", MiscConst.WhisperFutureYou)] +[Script("spell_wyrmrest_defender_whisper_to_controller_random", MiscConst.WhisperDefender)] +[Script("spell_past_you_whisper_to_controller_random", MiscConst.WhisperPastYou)] +class spell_gen_whisper_to_controller_random(uint text) : SpellScript +{ + void HandleScript(uint effIndex) + { + // Same for all spells + if (!RandomHelper.randChance(20)) + return; + + Creature target = GetHitCreature(); + if (target != null) + { + TempSummon targetSummon = target.ToTempSummon(); + if (targetSummon != null) + { + Player player = targetSummon.GetSummonerUnit().ToPlayer(); + if (player != null) + targetSummon.GetAI().Talk(text, player); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_eject_all_passengers : SpellScript +{ + void RemoveVehicleAuras() + { + Vehicle vehicle = GetHitUnit().GetVehicleKit(); + if (vehicle != null) + vehicle.RemoveAllPassengers(); + } + + public override void Register() + { + AfterHit.Add(new(RemoveVehicleAuras)); + } +} + +[Script] +class spell_gen_eject_passenger : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (!ValidateSpellEffect((spellInfo.Id, 0))) + return false; + if (spellInfo.GetEffect(0).CalcValue() < 1) + return false; + return true; + } + + void EjectPassenger(uint effIndex) + { + Vehicle vehicle = GetHitUnit().GetVehicleKit(); + if (vehicle != null) + { + Unit passenger = vehicle.GetPassenger((sbyte)(GetEffectValue() - 1)); + if (passenger != null) + passenger.ExitVehicle(); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(EjectPassenger, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script("spell_gen_eject_passenger_1", 0)] +[Script("spell_gen_eject_passenger_3", 2)] +class spell_gen_eject_passenger_with_seatId(sbyte seatId) : SpellScript() +{ + void EjectPassenger(uint effIndex) + { + Vehicle vehicle = GetHitUnit().GetVehicleKit(); + if (vehicle != null) + { + Unit passenger = vehicle.GetPassenger(seatId); + if (passenger != null) + passenger.ExitVehicle(); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(EjectPassenger, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_gm_freeze : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GmFreeze); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // Do what was done before to the target in HandleFreezeCommand + Player player = GetTarget().ToPlayer(); + if (player != null) + { + // stop combat + make player unattackable + duel stop + stop some spells + player.SetFaction(FactionTemplates.Friendly); + player.CombatStop(); + if (player.IsNonMeleeSpellCast(true)) + player.InterruptNonMeleeSpells(true); + player.SetUnitFlag(UnitFlags.NonAttackable); + + // if player class = hunter || warlock remove pet if alive + if ((player.GetClass() == Class.Hunter) || (player.GetClass() == Class.Warlock)) + { + Pet pet = player.GetPet(); + if (pet != null) + { + pet.SavePetToDB(PetSaveMode.AsCurrent); + // not let dismiss dead pet + if (pet.IsAlive()) + player.RemovePet(pet, PetSaveMode.NotInSlot); + } + } + } + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // Do what was done before to the target in HandleUnfreezeCommand + Player player = GetTarget().ToPlayer(); + if (player != null) + { + // Reset player faction + allow combat + allow duels + player.SetFactionForRace(player.GetRace()); + player.RemoveUnitFlag(UnitFlags.NonAttackable); + // save player + player.SaveToDB(); + } + } + + public override void Register() + { + OnEffectApply.Add(new(OnApply, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); + } +} + +[Script] +class spell_gen_stand : SpellScript +{ + void HandleScript(uint effIndex) + { + Creature target = GetHitCreature(); + if (target == null) + return; + + target.SetStandState(UnitStandStateType.Stand); + target.HandleEmoteCommand(Emote.StateNone); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_mixology_bonus : AuraScript +{ + int bonus = 0; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Mixology) && ValidateSpellEffect((spellInfo.Id, 0)); + } + + public override bool Load() + { + return GetCaster() != null && GetCaster().IsPlayer(); + } + + void SetBonusValueForEffect(uint effIndex, int value, AuraEffect aurEff) + { + if (aurEff.GetEffIndex() == effIndex) + bonus = value; + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + if (GetCaster().HasAura(SpellIds.Mixology) && GetCaster().HasSpell(GetEffectInfo(0).TriggerSpell)) + { + switch (GetId()) + { + case SpellIds.WeakTrollsBloodElixir: + case SpellIds.MagebloodElixir: + bonus = amount; break; - case BattleGroundTeamId.Horde: - amount = WorldStateMgr.GetValue(WorldStates.WarModeHordeBuffValue, target.GetMap()); + case SpellIds.ElixirOfFrostPower: + case SpellIds.LesserFlaskOfToughness: + case SpellIds.LesserFlaskOfResistance: + bonus = MathFunctions.CalculatePct(amount, 80); + break; + case SpellIds.ElixirOfMinorDefense: + case SpellIds.ElixirOfLionsStrength: + case SpellIds.ElixirOfMinorAgility: + case SpellIds.MajorTrollsBlloodElixir: + case SpellIds.ElixirOfShadowPower: + case SpellIds.ElixirOfBruteForce: + case SpellIds.MightyTrollsBloodElixir: + case SpellIds.ElixirOfGreaterFirepower: + case SpellIds.OnslaughtElixir: + case SpellIds.EarthenElixir: + case SpellIds.ElixirOfMajorAgility: + case SpellIds.FlaskOfTheTitans: + case SpellIds.FlaskOfRelentlessAssault: + case SpellIds.FlaskOfStoneblood: + case SpellIds.ElixirOfMinorAccuracy: + bonus = MathFunctions.CalculatePct(amount, 50); + break; + case SpellIds.ElixirOfProtection: + bonus = 280; + break; + case SpellIds.ElixirOfMajorDefense: + bonus = 200; + break; + case SpellIds.ElixirOfGreaterDefense: + case SpellIds.ElixirOfSuperiorDefense: + bonus = 140; + break; + case SpellIds.ElixirOfFortitude: + bonus = 100; + break; + case SpellIds.FlaskOfEndlessRage: + bonus = 82; + break; + case SpellIds.ElixirOfDefense: + bonus = 70; + break; + case SpellIds.ElixirOfDemonslaying: + bonus = 50; + break; + case SpellIds.FlaskOfTheFrostWyrm: + bonus = 47; + break; + case SpellIds.WrathElixir: + bonus = 32; + break; + case SpellIds.ElixirOfMajorFrostPower: + case SpellIds.ElixirOfMajorFirepower: + case SpellIds.ElixirOfMajorShadowPower: + bonus = 29; + break; + case SpellIds.ElixirOfMightyToughts: + bonus = 27; + break; + case SpellIds.FlaskOfSupremePower: + case SpellIds.FlaskOfBlindingLight: + case SpellIds.FlaskOfPureDeath: + case SpellIds.ShadowpowerElixir: + bonus = 23; + break; + case SpellIds.ElixirOfMightyAgility: + case SpellIds.FlaskOfDistilledWisdom: + case SpellIds.ElixirOfSpirit: + case SpellIds.ElixirOfMightyStrength: + case SpellIds.FlaskOfPureMojo: + case SpellIds.ElixirOfAccuracy: + case SpellIds.ElixirOfDeadlyStrikes: + case SpellIds.ElixirOfMightyDefense: + case SpellIds.ElixirOfExpertise: + case SpellIds.ElixirOfArmorPiercing: + case SpellIds.ElixirOfLightningSpeed: + bonus = 20; + break; + case SpellIds.FlaskOfChromaticResistance: + bonus = 17; + break; + case SpellIds.ElixirOfMinorFortitude: + case SpellIds.ElixirOfMajorStrength: + bonus = 15; + break; + case SpellIds.FlaskOfMightyRestoration: + bonus = 13; + break; + case SpellIds.ArcaneElixir: + bonus = 12; + break; + case SpellIds.ElixirOfGreaterAgility: + case SpellIds.ElixirOfGiants: + bonus = 11; + break; + case SpellIds.ElixirOfAgility: + case SpellIds.ElixirOfGreaterIntellect: + case SpellIds.ElixirOfSages: + case SpellIds.ElixirOfIronskin: + case SpellIds.ElixirOfMightyMageblood: + bonus = 10; + break; + case SpellIds.ElixirOfHealingPower: + bonus = 9; + break; + case SpellIds.ElixirOfDraenicWisdom: + case SpellIds.GurusElixir: + bonus = 8; + break; + case SpellIds.ElixirOfFirepower: + case SpellIds.ElixirOfMajorMageblood: + case SpellIds.ElixirOfMastery: + bonus = 6; + break; + case SpellIds.ElixirOfLesserAgility: + case SpellIds.ElixirOfOgresStrength: + case SpellIds.ElixirOfWisdom: + case SpellIds.ElixirOfTheMongoose: + bonus = 5; + break; + case SpellIds.StrongTrollsBloodElixir: + case SpellIds.FlaskOfChromaticWonder: + bonus = 4; + break; + case SpellIds.ElixirOfEmpowerment: + bonus = -10; + break; + case SpellIds.AdeptsElixir: + SetBonusValueForEffect(0, 13, aurEff); + SetBonusValueForEffect(1, 13, aurEff); + SetBonusValueForEffect(2, 8, aurEff); + break; + case SpellIds.ElixirOfMightyFortitude: + SetBonusValueForEffect(0, 160, aurEff); + break; + case SpellIds.ElixirOfMajorFortitude: + SetBonusValueForEffect(0, 116, aurEff); + SetBonusValueForEffect(1, 6, aurEff); + break; + case SpellIds.FelStrengthElixir: + SetBonusValueForEffect(0, 40, aurEff); + SetBonusValueForEffect(1, 40, aurEff); + break; + case SpellIds.FlaskOfFortification: + SetBonusValueForEffect(0, 210, aurEff); + SetBonusValueForEffect(1, 5, aurEff); + break; + case SpellIds.GreaterArcaneElixir: + SetBonusValueForEffect(0, 19, aurEff); + SetBonusValueForEffect(1, 19, aurEff); + SetBonusValueForEffect(2, 5, aurEff); + break; + case SpellIds.ElixirOfGianthGrowth: + SetBonusValueForEffect(0, 5, aurEff); break; default: + Log.outError(LogFilter.Spells, $"SpellId {GetId()} couldn't be processed in spell_gen_mixology_bonus"); break; } - } - - public override void Register() - { - SpellInfo spellInfo = SpellMgr.GetSpellInfo(m_scriptSpellId, Difficulty.None); - - if (spellInfo.HasAura(AuraType.ModXpPct)) - DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModXpPct)); - - if (spellInfo.HasAura(AuraType.ModXpQuestPct)) - DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModXpQuestPct)); - - if (spellInfo.HasAura(AuraType.ModCurrencyGainFromSource)) - DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModCurrencyGainFromSource)); - - if (spellInfo.HasAura(AuraType.ModMoneyGain)) - DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModMoneyGain)); - - if (spellInfo.HasAura(AuraType.ModAnimaGain)) - DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModAnimaGain)); - - if (spellInfo.HasAura(AuraType.Dummy)) - DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.Dummy)); + amount += bonus; } } - [Script] - class spell_defender_of_azeroth_death_gate_selector : SpellScript + public override void Register() { - const uint SpellDeathGateTeleportStormwind = 316999; - const uint SpellDeathGateTeleportOrgrimmar = 317000; + DoEffectCalcAmount.Add(new(CalculateAmount, SpellConst.EffectAll, AuraType.Any)); + } +} - const uint QuestDefenderOfAzerothAlliance = 58902; - const uint QuestDefenderOfAzerothHorde = 58903; - - (WorldLocation, uint) StormwindInnLoc = (new(0, -8868.1f, 675.82f, 97.9f, 5.164778709411621093f), 5148); - (WorldLocation, uint) OrgrimmarInnLoc = (new(1, 1573.18f, -4441.62f, 16.06f, 1.818284034729003906f), 8618); - - public override bool Validate(SpellInfo spell) +[Script] +class spell_gen_landmine_knockback_achievement : SpellScript +{ + void HandleScript(uint effIndex) + { + Player target = GetHitPlayer(); + if (target != null) { - return ValidateSpellInfo(SpellDeathGateTeleportStormwind, SpellDeathGateTeleportOrgrimmar); - } - - void HandleDummy(uint effIndex) - { - Player player = GetHitUnit().ToPlayer(); - if (player == null) + Aura aura = GetHitAura(); + if (aura == null || aura.GetStackAmount() < 10) return; - if (player.GetQuestStatus(QuestDefenderOfAzerothAlliance) == QuestStatus.None && player.GetQuestStatus(QuestDefenderOfAzerothHorde) == QuestStatus.None) - return; - - var (loc, areaId) = player.GetTeam() == Team.Alliance ? StormwindInnLoc : OrgrimmarInnLoc; - player.SetHomebind(loc, areaId); - player.SendBindPointUpdate(); - player.SendPlayerBound(player.GetGUID(), areaId); - - player.CastSpell(player, player.GetTeam() == Team.Alliance ? SpellDeathGateTeleportStormwind : SpellDeathGateTeleportOrgrimmar); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + target.CastSpell(target, SpellIds.LandmineKnockbackAchievement, true); } } - [Script] - class spell_defender_of_azeroth_speak_with_mograine : SpellScript + public override void Register() { - const uint NpcNazgrim = 161706; - const uint NpcTrollbane = 161707; - const uint NpcWhitemane = 161708; - - void HandleDummy(uint effIndex) - { - if (GetCaster() == null) - return; - - Player player = GetCaster().ToPlayer(); - if (player == null) - return; - - Creature nazgrim = GetHitUnit().FindNearestCreature(NpcNazgrim, 10.0f); - if (nazgrim != null) - nazgrim.HandleEmoteCommand(Emote.OneshotPoint, player); - Creature trollbane = GetHitUnit().FindNearestCreature(NpcTrollbane, 10.0f); - if (trollbane != null) - trollbane.HandleEmoteCommand(Emote.OneshotPoint, player); - Creature whitemane = GetHitUnit().FindNearestCreature(NpcWhitemane, 10.0f); - if (whitemane != null) - whitemane.HandleEmoteCommand(Emote.OneshotPoint, player); - - // @Todo: spawntracking - show death gate for casting player - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); } +} - [Script] // 118301 - Summon Battle Pet - class spell_summon_battle_pet : SpellScript +[Script] // 34098 - ClearAllDebuffs +class spell_gen_clear_debuffs : SpellScript +{ + void HandleScript(uint effIndex) { - void HandleSummon(uint effIndex) + Unit target = GetHitUnit(); + if (target != null) { - uint creatureId = (uint)GetSpellValue().EffectBasePoints[effIndex]; - if (ObjectMgr.GetCreatureTemplate(creatureId) != null) + target.RemoveOwnedAuras(aura => { - PreventHitDefaultEffect(effIndex); - - Unit caster = GetCaster(); - var properties = CliDB.SummonPropertiesStorage.LookupByKey((uint)GetEffectInfo().MiscValueB); - TimeSpan duration = TimeSpan.FromMilliseconds(GetSpellInfo().CalcDuration(caster)); - Position pos = GetHitDest().GetPosition(); - - Creature summon = caster.GetMap().SummonCreature(creatureId, pos, properties, duration, caster, GetSpellInfo().Id); - if (summon != null) - summon.SetImmuneToAll(true); - } - } - - public override void Register() - { - OnEffectHit.Add(new(HandleSummon, 0, SpellEffectName.Summon)); + SpellInfo spellInfo = aura.GetSpellInfo(); + return !spellInfo.IsPositive() && !spellInfo.IsPassive(); + }); } } - [Script] // 132334 - Trainer Heal Cooldown (Serverside) - class spell_gen_trainer_heal_cooldown : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_gen_pony_mount_check : AuraScript +{ + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + Player owner = caster.GetOwner().ToPlayer(); + if (owner == null || !owner.HasAchieved(MiscConst.AchievPonyUp)) + return; + + if (owner.IsMounted()) { - return ValidateSpellInfo(SharedConst.SpellReviveBattlePets); + caster.Mount(MiscConst.MountPony); + caster.SetSpeedRate(UnitMoveType.Run, owner.GetSpeedRate(UnitMoveType.Run)); } - - public override bool Load() + else if (caster.IsMounted()) { - return GetUnitOwner().IsPlayer(); - } - - void UpdateReviveBattlePetCooldown(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Player target = GetUnitOwner().ToPlayer(); - SpellInfo reviveBattlePetSpellInfo = SpellMgr.GetSpellInfo(SharedConst.SpellReviveBattlePets, Difficulty.None); - - if (target.GetSession().GetBattlePetMgr().IsBattlePetSystemEnabled()) - { - TimeSpan expectedCooldown = TimeSpan.FromMilliseconds(GetAura().GetMaxDuration()); - var remainingCooldown = target.GetSpellHistory().GetRemainingCategoryCooldown(reviveBattlePetSpellInfo); - if (remainingCooldown > TimeSpan.Zero) - { - if (remainingCooldown < expectedCooldown) - target.GetSpellHistory().ModifyCooldown(reviveBattlePetSpellInfo, expectedCooldown - remainingCooldown); - } - else - { - target.GetSpellHistory().StartCooldown(reviveBattlePetSpellInfo, 0, null, false, expectedCooldown); - } - } - } - - public override void Register() - { - OnEffectApply.Add(new(UpdateReviveBattlePetCooldown, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + caster.Dismount(); + caster.SetSpeedRate(UnitMoveType.Run, owner.GetSpeedRate(UnitMoveType.Run)); } } - [Script] // 45313 - Anchor Here - class spell_gen_anchor_here : SpellScript + public override void Register() { - void HandleScript(uint effIndex) - { - Creature creature = GetHitCreature(); - if (creature != null) - creature.SetHomePosition(creature.GetPositionX(), creature.GetPositionY(), creature.GetPositionZ(), creature.GetOrientation()); - } + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} - public override void Register() +// 40350 - Corrupting Plague +class CorruptingPlagueSearcher(Unit obj, float distance) : ICheck +{ + public bool Invoke(Unit u) + { + if (obj.GetDistance2d(u) < distance && + (u.GetEntry() == CreatureIds.ApexisFlayer || u.GetEntry() == CreatureIds.ShardHideBoar || u.GetEntry() == CreatureIds.AetherRay) && + !u.HasAura(SpellIds.CorruptingPlague)) + return true; + + return false; + } +} + +[Script] // 40349 - Corrupting Plague +class spell_corrupting_plague_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CorruptingPlague); + } + + void OnPeriodic(AuraEffect aurEff) + { + Unit owner = GetTarget(); + + List targets = new(); + CorruptingPlagueSearcher creature_check = new(owner, 15.0f); + CreatureListSearcher creature_searcher = new(owner, targets, creature_check); + Cell.VisitGridObjects(owner, creature_searcher, 15.0f); + + if (!targets.Empty()) + return; + + PreventDefaultAction(); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicTriggerSpell)); + } +} + +// 40307 - Stasis Field +class StasisFieldSearcher(Unit obj, float distance) : ICheck +{ + public bool Invoke(Unit u) + { + if (obj.GetDistance2d(u) < distance && + (u.GetEntry() == CreatureIds.ApexisFlayer || u.GetEntry() == CreatureIds.ShardHideBoar || u.GetEntry() == CreatureIds.AetherRay || u.GetEntry() == CreatureIds.DaggertailLizard) && + !u.HasAura(SpellIds.StasisField)) + return true; + + return false; + } +} + +[Script] // 40306 - Stasis Field +class spell_stasis_field_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StasisField); + } + + void OnPeriodic(AuraEffect aurEff) + { + Unit owner = GetTarget(); + + List targets = new(); + StasisFieldSearcher creature_check = new(owner, 15.0f); + CreatureListSearcher creature_searcher = new(owner, targets, creature_check); + Cell.VisitGridObjects(owner, creature_searcher, 15.0f); + + if (!targets.Empty()) + return; + + PreventDefaultAction(); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] +class spell_gen_vehicle_control_link : AuraScript +{ + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.SiegeTankControl); //aurEff.GetAmount() + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 34779 - Freezing Circle +class spell_freezing_circle : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FreezingCirclePitOfSaronNormal, SpellIds.FreezingCirclePitOfSaronHeroic, SpellIds.FreezingCircle, SpellIds.FreezingCircleScenario); + } + + void HandleDamage(uint effIndex) + { + Unit caster = GetCaster(); + uint spellId = 0; + Map map = caster.GetMap(); + + if (map.IsDungeon()) + spellId = map.IsHeroic() ? SpellIds.FreezingCirclePitOfSaronHeroic : SpellIds.FreezingCirclePitOfSaronNormal; + else + spellId = map.GetId() == MiscConst.MapIdBloodInTheSnowScenario ? SpellIds.FreezingCircleScenario : SpellIds.FreezingCircle; + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, GetCastDifficulty()); + if (spellInfo != null && !spellInfo.GetEffects().Empty()) + SetHitDamage(spellInfo.GetEffect(0).CalcValue()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDamage, 1, SpellEffectName.SchoolDamage)); + } +} + +[Script] // Used for some spells cast by vehicles or charmed creatures that do not send a cooldown event on their own +class spell_gen_charmed_unit_spell_cooldown : SpellScript +{ + void HandleCast() + { + Unit caster = GetCaster(); + Player owner = caster.GetCharmerOrOwnerPlayerOrPlayerItself(); + if (owner != null) { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + SpellCooldownPkt spellCooldown = new(); + spellCooldown.Caster = owner.GetGUID(); + spellCooldown.Flags = SpellCooldownFlags.None; + spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(GetSpellInfo().Id, GetSpellInfo().RecoveryTime)); + owner.SendPacket(spellCooldown); } } - [Script] // 147066 - (Serverside/Non-Db2) Generic - Mount Check Aura - class spell_gen_mount_check_AuraScript : AuraScript + public override void Register() { - void OnPeriodic(AuraEffect aurEff) + OnCast.Add(new(HandleCast)); + } +} + +[Script] +class spell_gen_cannon_blast : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CannonBlast); + } + + void HandleScript(uint effIndex) + { + int bp = GetEffectValue(); + Unit target = GetHitUnit(); + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.AddSpellMod(SpellValueMod.BasePoint0, bp); + target.CastSpell(target, SpellIds.CannonBlastDamage, args); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 37751 - Submerged +class spell_gen_submerged : SpellScript +{ + void HandleScript(uint effIndex) + { + Creature target = GetHitCreature(); + if (target != null) + target.SetStandState(UnitStandStateType.Submerged); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 169869 - Transformation Sickness +class spell_gen_decimatus_transformation_sickness : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) + target.SetHealth(target.CountPctFromMaxHealth(25)); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 189491 - Summon Towering Infernal. +class spell_gen_anetheron_summon_towering_infernal : SpellScript +{ + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +class MarkTargetHellfireFilter +{ + public bool Invoke(WorldObject target) + { + Unit unit = target.ToUnit(); + if (unit != null) + return unit.GetPowerType() != PowerType.Mana; + return false; + } +} + +[Script] +class spell_gen_mark_of_kazrogal_hellfire : SpellScript +{ + void FilterTargets(List targets) + { + targets.RemoveAll(new MarkTargetHellfireFilter().Invoke); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaEnemy)); + } +} + +[Script] +class spell_gen_mark_of_kazrogal_hellfire_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MarkOfKazrogalDamageHellfire); + } + + void OnPeriodic(AuraEffect aurEff) + { + Unit target = GetTarget(); + + if (target.GetPower(PowerType.Mana) == 0) { - Unit target = GetTarget(); - uint mountDisplayId = 0; - - TempSummon tempSummon = target.ToTempSummon(); - if (tempSummon == null) - return; - - Player summoner = tempSummon.GetSummoner()?.ToPlayer(); - if (summoner == null) - return; - - if (summoner.IsMounted() && (!summoner.IsInCombat() || summoner.IsFlying())) - { - CreatureSummonedData summonedData = ObjectMgr.GetCreatureSummonedData(tempSummon.GetEntry()); - if (summonedData != null) - { - if (summoner.IsFlying() && summonedData.FlyingMountDisplayID.HasValue) - mountDisplayId = summonedData.FlyingMountDisplayID.Value; - else if (summonedData.GroundMountDisplayID.HasValue) - mountDisplayId = summonedData.GroundMountDisplayID.Value; - } - } - - if (mountDisplayId != target.GetMountDisplayId()) - target.SetMountDisplayId(mountDisplayId); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicDummy)); + target.CastSpell(target, SpellIds.MarkOfKazrogalDamageHellfire, aurEff); + // Remove aura + SetDuration(0); } } - [Script] // 274738 - Ancestral Call (Mag'har Orc Racial) - class spell_gen_ancestral_call : SpellScript + public override void Register() { - const uint SpellRictusOfTheLaughingSkull = 274739; - const uint SpellZealOfTheBurningBlade = 274740; - const uint SpellFerocityOfTheFrostwolf = 274741; - const uint SpellMightOfTheBlackrock = 274742; + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PowerBurn)); + } +} - public override bool Validate(SpellInfo spell) +[Script] +class spell_gen_azgalor_rain_of_fire_hellfire_citadel : SpellScript +{ + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 99947 - Face Rage +class spell_gen_face_rage : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FaceRage) + && ValidateSpellEffect((spellInfo.Id, 2)); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(GetEffectInfo(2).TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); + } +} + +[Script] // 187213 - Impatient Mind +class spell_gen_impatient_mind : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImpatientMind); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 209352 - Boost 2.0 [Paladin+Priest] - Watch for Shield +class spell_gen_boost_2_0_paladin_priest_watch_for_shield : AuraScript +{ + static uint SpellPowerWordShield = 17; + static uint SpellDivineShield = 642; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellPowerWordShield, SpellDivineShield); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + SpellInfo spellInfo = procInfo.GetSpellInfo(); + return spellInfo != null && (spellInfo.Id == SpellPowerWordShield || spellInfo.Id == SpellDivineShield); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +// 269083 - Enlisted +[Script] // 282559 - Enlisted +class spell_gen_war_mode_enlisted : AuraScript +{ + void CalcWarModeBonus(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player target = GetUnitOwner().ToPlayer(); + if (target == null) + return; + + switch (target.GetTeamId()) { - return ValidateSpellInfo(SpellRictusOfTheLaughingSkull, SpellZealOfTheBurningBlade, SpellFerocityOfTheFrostwolf, SpellMightOfTheBlackrock); + case BattleGroundTeamId.Alliance: + amount = Global.WorldStateMgr.GetValue(WorldStates.WarModeAllianceBuffValue, target.GetMap()); + break; + case BattleGroundTeamId.Horde: + amount = Global.WorldStateMgr.GetValue(WorldStates.WarModeHordeBuffValue, target.GetMap()); + break; + default: + break; } + } - uint[] AncestralCallBuffs = { SpellRictusOfTheLaughingSkull, SpellZealOfTheBurningBlade, SpellFerocityOfTheFrostwolf, SpellMightOfTheBlackrock }; + public override void Register() + { + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(m_scriptSpellId, Difficulty.None); - void HandleOnCast() + if (spellInfo.HasAura(AuraType.ModXpPct)) + DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModXpPct)); + + if (spellInfo.HasAura(AuraType.ModXpQuestPct)) + DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModXpQuestPct)); + + if (spellInfo.HasAura(AuraType.ModCurrencyGainFromSource)) + DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModCurrencyGainFromSource)); + + if (spellInfo.HasAura(AuraType.ModMoneyGain)) + DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModMoneyGain)); + + if (spellInfo.HasAura(AuraType.ModAnimaGain)) + DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.ModAnimaGain)); + + if (spellInfo.HasAura(AuraType.Dummy)) + DoEffectCalcAmount.Add(new(CalcWarModeBonus, SpellConst.EffectAll, AuraType.Dummy)); + } +} + +[Script] +class spell_defender_of_azeroth_death_gate_selector : SpellScript +{ + BindLocation StormwindInnLoc = new(0, -8868.1f, 675.82f, 97.9f, 5.164778709411621093f, 5148); + BindLocation OrgrimmarInnLoc = new(1, 1573.18f, -4441.62f, 16.06f, 1.818284034729003906f, 8618); + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DeathGateTeleportStormwind, SpellIds.DeathGateTeleportOrgrimmar); + } + + void HandleDummy(uint effIndex) + { + Player player = GetHitUnit().ToPlayer(); + if (player == null) + return; + + if (player.GetQuestStatus(MiscConst.QuestDefenderOfAzerothAlliance) == QuestStatus.None && player.GetQuestStatus(MiscConst.QuestDefenderOfAzerothHorde) == QuestStatus.None) + return; + + BindLocation bindLoc = player.GetTeam() == Team.Alliance ? StormwindInnLoc : OrgrimmarInnLoc; + player.SetHomebind(bindLoc.Loc, bindLoc.AreaId); + player.SendBindPointUpdate(); + player.SendPlayerBound(player.GetGUID(), bindLoc.AreaId); + + player.CastSpell(player, player.GetTeam() == Team.Alliance ? SpellIds.DeathGateTeleportStormwind : SpellIds.DeathGateTeleportOrgrimmar); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } + + struct BindLocation + { + public WorldLocation Loc; + public uint AreaId; + + public BindLocation(uint mapId, float x, float y, float z, float orientation, uint areaId) { + Loc = new(mapId, x, y, z, orientation); + AreaId = areaId; + } + } +} + +[Script] +class spell_defender_of_azeroth_speak_with_mograine : SpellScript +{ + void HandleDummy(uint effIndex) + { + if (GetCaster() == null) + return; + + Player player = GetCaster().ToPlayer(); + if (player == null) + return; + Creature nazgrim = GetHitUnit().FindNearestCreature(CreatureIds.Nazgrim, 10.0f); + if (nazgrim != null) + nazgrim.HandleEmoteCommand(Emote.OneshotPoint, player); + Creature trollbane = GetHitUnit().FindNearestCreature(CreatureIds.Trollbane, 10.0f); + if (trollbane != null) + trollbane.HandleEmoteCommand(Emote.OneshotPoint, player); + Creature whitemane = GetHitUnit().FindNearestCreature(CreatureIds.Whitemane, 10.0f); + if (whitemane != null) + whitemane.HandleEmoteCommand(Emote.OneshotPoint, player); + + // @Todo: spawntracking - show death gate for casting player + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 118301 - Summon Battle Pet +class spell_summon_battle_pet : SpellScript +{ + void HandleSummon(uint effIndex) + { + uint creatureId = (uint)GetSpellValue().EffectBasePoints[effIndex]; + if (Global.ObjectMgr.GetCreatureTemplate(creatureId) != null) + { + PreventHitDefaultEffect(effIndex); + Unit caster = GetCaster(); - uint spellId = AncestralCallBuffs.SelectRandom(); + var properties = CliDB.SummonPropertiesStorage.LookupByKey((uint)GetEffectInfo().MiscValueB); + TimeSpan duration = TimeSpan.FromSeconds(GetSpellInfo().CalcDuration(caster)); + Position pos = GetHitDest().GetPosition(); - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnCast.Add(new(HandleOnCast)); + Creature summon = caster.GetMap().SummonCreature(creatureId, pos, properties, duration, caster, GetSpellInfo().Id); + if (summon != null) + summon.SetImmuneToAll(true); } } - [Script] // 83477 - Eject Passengers 3-8 - class spell_gen_eject_passengers_3_8 : SpellScript + public override void Register() { - void HandleScriptEffect(uint effIndex) - { - Vehicle vehicle = GetHitUnit().GetVehicleKit(); - if (vehicle == null) - return; + OnEffectHit.Add(new(HandleSummon, 0, SpellEffectName.Summon)); + } +} - for (sbyte i = 2; i < 8; i++) - vehicle.GetPassenger(i)?.ExitVehicle(); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } +[Script] // 132334 - Trainer Heal Cooldown (Serverside) +class spell_gen_trainer_heal_cooldown : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SharedConst.SpellReviveBattlePets); } - [Script] // 83781 - Reverse Cast Ride Vehicle - class spell_gen_reverse_cast_target_to_caster_triggered : SpellScript + public override bool Load() { - void HandleScript(uint effIndex) - { - GetHitUnit().CastSpell(GetCaster(), (uint)GetSpellInfo().GetEffect(effIndex).CalcValue(), true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } + return GetUnitOwner().IsPlayer(); } - // Note: this spell unsummons any creature owned by the caster. Set appropriate target conditions on the Db. - // 84065 - Despawn All Summons - // 83935 - Despawn All Summons - [Script] // 160938 - Despawn All Summons (Garrison Intro Only) - class spell_gen_despawn_all_summons_owned_by_caster : SpellScript + void UpdateReviveBattlePetCooldown(AuraEffect aurEff, AuraEffectHandleModes mode) { - void HandleScriptEffect(uint effIndex) + Player target = GetUnitOwner().ToPlayer(); + SpellInfo reviveBattlePetSpellInfo = Global.SpellMgr.GetSpellInfo(SharedConst.SpellReviveBattlePets, Difficulty.None); + + if (target.GetSession().GetBattlePetMgr().IsBattlePetSystemEnabled()) { - Unit caster = GetCaster(); - if (caster != null) + TimeSpan expectedCooldown = TimeSpan.FromSeconds(GetAura().GetMaxDuration()); + TimeSpan remainingCooldown = target.GetSpellHistory().GetRemainingCategoryCooldown(reviveBattlePetSpellInfo); + if (remainingCooldown > TimeSpan.Zero) { - Creature target = GetHitCreature(); + if (remainingCooldown < expectedCooldown) + target.GetSpellHistory().ModifyCooldown(reviveBattlePetSpellInfo, expectedCooldown - remainingCooldown); + } + else + { + target.GetSpellHistory().StartCooldown(reviveBattlePetSpellInfo, 0, null, false, expectedCooldown); + } + } + } - if (target.GetOwner() == caster) - target.DespawnOrUnsummon(); + public override void Register() + { + OnEffectApply.Add(new(UpdateReviveBattlePetCooldown, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 45313 - Anchor Here +class spell_gen_anchor_here : SpellScript +{ + void HandleScript(uint effIndex) + { + Creature creature = GetHitCreature(); + if (creature != null) + creature.SetHomePosition(creature.GetPositionX(), creature.GetPositionY(), creature.GetPositionZ(), creature.GetOrientation()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 147066 - (Serverside/Non-DB2) Generic - Mount Check Aura +class spell_gen_mount_check_aura : AuraScript +{ + void OnPeriodic(AuraEffect aurEff) + { + Unit target = GetTarget(); + uint mountDisplayId = 0; + + TempSummon tempSummon = target.ToTempSummon(); + if (tempSummon == null) + return; + + Player summoner = tempSummon.GetSummoner()?.ToPlayer(); + if (summoner == null) + return; + + if (summoner.IsMounted() && (!summoner.IsInCombat() || summoner.IsFlying())) + { + CreatureSummonedData summonedData = Global.ObjectMgr.GetCreatureSummonedData(tempSummon.GetEntry()); + if (summonedData != null) + { + if (summoner.IsFlying() && summonedData.FlyingMountDisplayID.HasValue) + mountDisplayId = summonedData.FlyingMountDisplayID.Value; + else if (summonedData.GroundMountDisplayID.HasValue) + mountDisplayId = summonedData.GroundMountDisplayID.Value; } } - public override void Register() + if (mountDisplayId != target.GetMountDisplayId()) + target.SetMountDisplayId(mountDisplayId); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 274738 - Ancestral Call (Mag'har Orc Racial) +class spell_gen_ancestral_call : SpellScript +{ + uint[] AncestralCallBuffs = [SpellIds.RictusOfTheLaughingSkull, SpellIds.ZealOfTheBurningBlade, SpellIds.FerocityOfTheFrostwolf, SpellIds.MightOfTheBlackrock]; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RictusOfTheLaughingSkull, SpellIds.ZealOfTheBurningBlade, SpellIds.FerocityOfTheFrostwolf, SpellIds.MightOfTheBlackrock); + } + + void HandleOnCast() + { + Unit caster = GetCaster(); + uint spellId = AncestralCallBuffs.SelectRandom(); + + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnCast.Add(new(HandleOnCast)); + } +} + +[Script] // 83477 - Eject Passengers 3-8 +class spell_gen_eject_passengers_3_8 : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + Vehicle vehicle = GetHitUnit().GetVehicleKit(); + if (vehicle == null) + return; + + for (sbyte i = 2; i < 8; i++) { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + Unit passenger = vehicle.GetPassenger(i); + if (passenger != null) + passenger.ExitVehicle(); } } - [Script] // 8613 - Skinning - class spell_gen_skinning : SpellScript + public override void Register() { - const uint SpellClassicSkinning = 265856; - const uint SpellOutlandSkinning = 265858; - const uint SpellNorthrendSkinning = 265860; - const uint SpellCataclysmSkinning = 265862; - const uint SpellPandariaSkinning = 265864; - const uint SpellDraenorSkinning = 265866; - const uint SpellLegionSkinning = 265868; - const uint SpellKulTiranSkinning = 265870; - const uint SpellZandalariSkinning = 265872; - const uint SpellShadowlandsSkinning = 308570; - const uint SpellDragonIslesSkinning = 366263; + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} - public override bool Validate(SpellInfo spell) +// 83781 - Reverse Cast Ride Vehicle +// 85299 - Reverse Cast Ride Seat 1 +[Script] // 258344 - Reverse Cast Ride Vehicle +class spell_gen_reverse_cast_target_to_caster_triggered : SpellScript +{ + void HandleScript(uint effIndex) + { + GetHitUnit().CastSpell(GetCaster(), (uint)GetSpellInfo().GetEffect(effIndex).CalcValue(), true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +// Note: this spell unsummons any creature owned by the caster. Set appropriate target conditions on the Db. +// 84065 - Despawn All Summons +// 83935 - Despawn All Summons +[Script] // 160938 - Despawn All Summons (Garrison Intro Only) +class spell_gen_despawn_all_summons_owned_by_caster : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + Unit caster = GetCaster(); + if (caster != null) { - return ValidateSpellInfo(SpellOutlandSkinning, SpellNorthrendSkinning, SpellCataclysmSkinning, SpellPandariaSkinning, SpellDraenorSkinning, SpellKulTiranSkinning, SpellZandalariSkinning, SpellShadowlandsSkinning, SpellDragonIslesSkinning); - } + Creature target = GetHitCreature(); - void HandleSkinningEffect(uint effIndex) - { - Player player = GetCaster().ToPlayer(); - if (player == null) - return; - - var contentTuning = CliDB.ContentTuningStorage.LookupByKey(GetHitUnit().GetContentTuning()); - if (contentTuning == null) - return; - - uint skinningSkill = player.GetProfessionSkillForExp(SkillType.Skinning, contentTuning.ExpansionID); - if (skinningSkill == 0) - return; - - // Autolearning missing skinning skill (Dragonflight) - uint getSkinningLearningSpellBySkill() - { - switch ((SkillType)skinningSkill) - { - case SkillType.OutlandSkinning: return SpellOutlandSkinning; - case SkillType.NorthrendSkinning: return SpellNorthrendSkinning; - case SkillType.CataclysmSkinning: return SpellCataclysmSkinning; - case SkillType.PandariaSkinning: return SpellPandariaSkinning; - case SkillType.DraenorSkinning: return SpellDraenorSkinning; - case SkillType.KulTiranSkinning: return player.GetTeam() == Team.Alliance ? SpellKulTiranSkinning : (player.GetTeam() == Team.Horde ? SpellZandalariSkinning : 0); - case SkillType.ShadowlandsSkinning: return SpellShadowlandsSkinning; - case SkillType.DragonIslesSkinning: return SpellDragonIslesSkinning; - case SkillType.ClassicSkinning: // Trainer only - case SkillType.LegionSkinning: // Quest only - default: break; - } - - return 0; - } - - if (!player.HasSkill(skinningSkill)) - { - uint spellId = getSkinningLearningSpellBySkill(); - if (spellId != 0) - player.CastSpell(null, spellId, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleSkinningEffect, 0, SpellEffectName.Skinning)); + if (target.GetOwner() == caster) + target.DespawnOrUnsummon(); } } - // 2825 - Bloodlust - // 32182 - Heroism - // 80353 - Time Warp - // 264667 - Primal Rage - // 390386 - Fury of the Aspects - // 146555 - Drums of Rage - // 178207 - Drums of Fury - // 230935 - Drums of the Mountain - // 256740 - Drums of the Maelstrom - // 309658 - Drums of Deathly Ferocity - // 381301 - Feral Hide Drums - [Script("spell_sha_bloodlust", SpellShamanSated)] - [Script("spell_sha_heroism", SpellShamanExhaustion)] - [Script("spell_mage_time_warp", SpellMageTemporalDisplacement)] - [Script("spell_hun_primal_rage", SpellHunterFatigued)] - [Script("spell_evo_fury_of_the_aspects", SpellEvokerExhaustion)] - [Script("spell_item_bloodlust_drums", SpellShamanExhaustion)] - class spell_gen_bloodlust : SpellScript + public override void Register() { - const uint SpellShamanSated = 57724; // Bloodlust - const uint SpellShamanExhaustion = 57723; // Heroism, Drums - const uint SpellMageTemporalDisplacement = 80354; - const uint SpellHunterFatigued = 264689; - const uint SpellEvokerExhaustion = 390435; + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} - uint _exhaustionSpellId; +[Script] // 8613 - Skinning +class spell_gen_skinning : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.OutlandSkinning, SpellIds.NorthrendSkinning, SpellIds.CataclysmSkinning, SpellIds.PandariaSkinning, SpellIds.DraenorSkinning, SpellIds.KulTiranSkinning, SpellIds.ZandalariSkinning, + SpellIds.ShadowlandsSkinning, SpellIds.DragonIslesSkinning); + } - public spell_gen_bloodlust(uint exhaustionSpellId) + void HandleSkinningEffect(uint effIndex) + { + Player player = GetCaster().ToPlayer(); + if (player == null) + return; + + var contentTuning = CliDB.ContentTuningStorage.LookupByKey(GetHitUnit().GetContentTuning()); + if (contentTuning == null) + return; + + SkillType skinningSkill = (SkillType)player.GetProfessionSkillForExp(SkillType.Skinning, contentTuning.ExpansionID); + if (skinningSkill == 0) + return; + + // Autolearning missing skinning skill (Dragonflight) + uint getSkinningLearningSpellBySkill = skinningSkill switch { - _exhaustionSpellId = exhaustionSpellId; + SkillType.OutlandSkinning => SpellIds.OutlandSkinning, + SkillType.NorthrendSkinning => SpellIds.NorthrendSkinning, + SkillType.CataclysmSkinning => SpellIds.CataclysmSkinning, + SkillType.PandariaSkinning => SpellIds.PandariaSkinning, + SkillType.DraenorSkinning => SpellIds.DraenorSkinning, + SkillType.KulTiranSkinning => player.GetTeam() == Team.Alliance ? SpellIds.KulTiranSkinning : (player.GetTeam() == Team.Horde ? SpellIds.ZandalariSkinning : 0), + SkillType.ShadowlandsSkinning => SpellIds.ShadowlandsSkinning, + SkillType.DragonIslesSkinning => SpellIds.DragonIslesSkinning, + _ => 0, + }; + + if (!player.HasSkill(skinningSkill)) + { + if (getSkinningLearningSpellBySkill != 0) + player.CastSpell(null, getSkinningLearningSpellBySkill, true); } + } - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellShamanSated, SpellShamanExhaustion, SpellMageTemporalDisplacement, SpellHunterFatigued, SpellEvokerExhaustion); - } + public override void Register() + { + OnEffectHitTarget.Add(new(HandleSkinningEffect, 0, SpellEffectName.Skinning)); + } +} - void FilterTargets(List targets) - { - targets.RemoveAll(target => +// 2825 - Bloodlust +// 32182 - Heroism +// 80353 - Time Warp +// 264667 - Primal Rage +// 390386 - Fury of the Aspects +// 146555 - Drums of Rage +// 178207 - Drums of Fury +// 230935 - Drums of the Mountain +// 256740 - Drums of the Maelstrom +// 309658 - Drums of Deathly Ferocity +// 381301 - Feral Hide Drums +[Script("spell_sha_bloodlust", SpellIds.ShamanSated)] +[Script("spell_sha_heroism", SpellIds.ShamanExhaustion)] +[Script("spell_mage_time_warp", SpellIds.MageTemporalDisplacement)] +[Script("spell_hun_primal_rage", SpellIds.HunterFatigued)] +[Script("spell_evo_fury_of_the_aspects", SpellIds.EvokerExhaustion)] +[Script("spell_item_bloodlust_drums", SpellIds.ShamanExhaustion)] +class spell_gen_bloodlust(uint exhaustionSpellId) : SpellScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShamanSated, SpellIds.ShamanExhaustion, SpellIds.MageTemporalDisplacement, SpellIds.HunterFatigued, SpellIds.EvokerExhaustion); + } + + void FilterTargets(List targets) + { + targets.RemoveAll(target => { Unit unit = target.ToUnit(); if (unit == null) return true; - return unit.HasAura(SpellShamanSated) - || unit.HasAura(SpellShamanExhaustion) - || unit.HasAura(SpellMageTemporalDisplacement) - || unit.HasAura(SpellHunterFatigued) - || unit.HasAura(SpellEvokerExhaustion); + return unit.HasAura(SpellIds.ShamanSated) + || unit.HasAura(SpellIds.ShamanExhaustion) + || unit.HasAura(SpellIds.MageTemporalDisplacement) + || unit.HasAura(SpellIds.HunterFatigued) + || unit.HasAura(SpellIds.EvokerExhaustion); }); - } - - void HandleHit(uint effIndex) - { - Unit target = GetHitUnit(); - target.CastSpell(target, _exhaustionSpellId, true); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitCasterAreaRaid)); - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitCasterAreaRaid)); - OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.ApplyAura)); - } } - // AoE resurrections by spirit guides - [Script] // 22012 - Spirit Heal - class spell_gen_spirit_heal_aoe : SpellScript + void HandleHit(uint effIndex) { - void FilterTargets(List targets) - { - Unit caster = GetCaster(); - targets.RemoveAll(target => - { - Player playerTarget = target.ToPlayer(); - if (playerTarget != null) - return !playerTarget.CanAcceptAreaSpiritHealFrom(caster); - - return true; - }); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - } + Unit target = GetHitUnit(); + target.CastSpell(target, exhaustionSpellId, true); } - // Personal resurrections in battlegrounds - [Script] // 156758 - Spirit Heal - class spell_gen_spirit_heal_personal : AuraScript + public override void Register() { - uint SpellSpiritHealEffect = 156763; + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitCasterAreaRaid)); + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitCasterAreaRaid)); + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.ApplyAura)); + } +} - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) +// AoE resurrections by spirit guides +[Script] // 22012 - Spirit Heal +class spell_gen_spirit_heal_aoe : SpellScript +{ + void FilterTargets(List targets) + { + Unit caster = GetCaster(); + targets.RemoveAll(target => { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; + Player playerTarget = target.ToPlayer(); + if (playerTarget != null) + return !playerTarget.CanAcceptAreaSpiritHealFrom(caster); - Player targetPlayer = GetTarget().ToPlayer(); - if (targetPlayer == null) - return; - - Unit caster = GetCaster(); - if (caster == null) - return; - - if (targetPlayer.CanAcceptAreaSpiritHealFrom(caster)) - caster.CastSpell(targetPlayer, SpellSpiritHealEffect); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + return true; + }); } - class RecastSpiritHealChannelEvent : BasicEvent + public override void Register() { - Unit _caster; + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} - public RecastSpiritHealChannelEvent(Unit caster) - { - _caster = caster; - } +// Personal resurrections in battlegrounds +[Script] // 156758 - Spirit Heal +class spell_gen_spirit_heal_personal : AuraScript +{ + uint SpellSpiritHealEffect = 156763; + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Player targetPlayer = GetTarget().ToPlayer(); + if (targetPlayer == null) + return; + + Unit caster = GetCaster(); + if (caster == null) + return; + + if (targetPlayer.CanAcceptAreaSpiritHealFrom(caster)) + caster.CastSpell(targetPlayer, SpellSpiritHealEffect); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 22011 - Spirit Heal Channel +class spell_gen_spirit_heal_channel : AuraScript +{ + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit target = GetTarget(); + target.m_Events.AddEventAtOffset(new RecastSpiritHealChannelEvent(target), TimeSpan.FromSeconds(1)); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + } + + class RecastSpiritHealChannelEvent(Unit caster) : BasicEvent() + { public override bool Execute(ulong e_time, uint p_time) { - if (_caster.GetChannelSpellId() == 0) - _caster.CastSpell(null, BattlegroundConst.SpellSpiritHealChannelAoE, false); + if (caster.GetChannelSpellId() == 0) + caster.CastSpell(null, BattlegroundConst.SpellSpiritHealChannelAoE, false); return true; } } +} - [Script] // 22011 - Spirit Heal Channel - class spell_gen_spirit_heal_channel : AuraScript +[Script] // 2584 - Waiting to Resurrect +class spell_gen_waiting_to_resurrect : AuraScript +{ + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; + Player targetPlayer = GetTarget().ToPlayer(); + if (targetPlayer == null) + return; - Unit target = GetTarget(); - target.m_Events.AddEventAtOffset(new RecastSpiritHealChannelEvent(target), TimeSpan.FromSeconds(1)); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); - } + targetPlayer.SetAreaSpiritHealer(null); } - [Script] // 2584 - Waiting to Resurrect - class spell_gen_waiting_to_resurrect : AuraScript + public override void Register() { - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Player targetPlayer = GetTarget().ToPlayer(); - if (targetPlayer == null) - return; + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - targetPlayer.SetAreaSpiritHealer(null); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } +// 157982 - Tranquility (Heal) +// 64844 - Divine Hymn (Heal) +// 114942 - Healing Tide (Heal) +[Script] // 115310 - Revival (Heal) +class spell_gen_major_healing_cooldown_modifier : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DruidTranquility, 2), (SpellIds.PriestDivineHymn, 1), (SpellIds.ShamanHealingTideTotem, 2), (SpellIds.MonkRevival, 4)); } - struct MajorPlayerHealingCooldownHelpers + void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) { - public const uint SpellDruidTranquility = 740; - public const uint SpellDruidTranquilityHeal = 157982; - public const uint SpellPriestDivineHymn = 64843; - public const uint SpellPriestDivineHymnHeal = 64844; - public const uint SpellPriestLuminousBarrier = 271466; - public const uint SpellShamanHealingTideTotem = 108280; - public const uint SpellShamanHealingTideTotemHeal = 114942; - public const uint SpellMonkRevival = 115310; - public const uint SpellEvokerRewind = 363534; + MathFunctions.AddPct(ref pctMod, MiscConst.GetBonusMultiplier(GetCaster(), GetSpellInfo().Id)); + } - public static float GetBonusMultiplier(Unit unit, uint spellId) + public override void Register() + { + CalcHealing.Add(new(CalculateHealingBonus)); + } +} + +// 157982 - Tranquility (Heal) +// 271466 - Luminous Barrier (Absorb) +[Script] // 363534 - Rewind (Heal) +class spell_gen_major_healing_cooldown_modifier_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DruidTranquility, 2), (SpellIds.PriestLuminousBarrier, 1), (SpellIds.EvokerRewind, 3)); + } + + void CalculateHealingBonus(AuraEffect aurEff, Unit victim, ref int damageOrHealing, ref int flatMod, ref float pctMod) + { + Unit caster = GetCaster(); + if (caster != null) + MathFunctions.AddPct(ref pctMod, MiscConst.GetBonusMultiplier(caster, GetSpellInfo().Id)); + } + + public override void Register() + { + DoEffectCalcDamageAndHealing.Add(new(CalculateHealingBonus, SpellConst.EffectAll, AuraType.Any)); + } +} + +[Script] // 50230 - Random Aggro (Taunt) +class spell_gen_random_aggro_taunt : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 0)) && ValidateSpellInfo((uint)spellInfo.GetEffect(0).BasePoints); + } + + void SelectRandomTarget(List targets) + { + if (targets.Empty()) + return; + + targets.RandomResize(1); + } + + void HandleTauntEffect(uint effIndex) + { + GetHitUnit().CastSpell(GetCaster(), (uint)GetSpellInfo().GetEffect(effIndex).BasePoints, new CastSpellExtraArgs(TriggerCastFlags.FullMask)); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(SelectRandomTarget, 0, Targets.UnitSrcAreaEnemy)); + OnEffectHitTarget.Add(new(HandleTauntEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +// 24931 - 100 Health +// 24959 - 500 Health +// 28838 - 1 Health +// 43645 - 1 Health +// 73342 - 1 Health +// 86562 - 1 Health +[Script("spell_gen_set_health_1", 1)] +[Script("spell_gen_set_health_100", 100)] +[Script("spell_gen_set_health_500", 500)] +class spell_gen_set_health(ulong health) : SpellScript +{ + void HandleHit(uint effIndex) + { + if (GetHitUnit().IsAlive() && health > 0) + GetHitUnit().SetHealth(health); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 128648 - Defending Cart Aura +class spell_bg_defending_cart_aura : SpellScript +{ + void FilterTargets(List targets) + { + if (targets.Empty()) + return; + + GameObject controlZone = GetControlZone(); + if (controlZone != null) { - // Note: if caster is not in a raid setting, is in PvP or while in arena combat with 5 or less allied players. - if (!unit.GetMap().IsRaid() || !unit.GetMap().IsBattleground()) + targets.RemoveAll(obj => { - uint bonusSpellId; - uint effIndex; - switch (spellId) - { - case SpellDruidTranquilityHeal: - bonusSpellId = SpellDruidTranquility; - effIndex = 2; - break; - case SpellPriestDivineHymnHeal: - bonusSpellId = SpellPriestDivineHymn; - effIndex = 1; - break; - case SpellPriestLuminousBarrier: - bonusSpellId = spellId; - effIndex = 1; - break; - case SpellShamanHealingTideTotemHeal: - bonusSpellId = SpellShamanHealingTideTotem; - effIndex = 2; - break; - case SpellMonkRevival: - bonusSpellId = spellId; - effIndex = 4; - break; - case SpellEvokerRewind: - bonusSpellId = spellId; - effIndex = 3; - break; - default: - return 0.0f; - } + Player player = obj.ToPlayer(); + if (player != null) + return SharedConst.GetTeamIdForTeam(player.GetBGTeam()) != controlZone.GetControllingTeam(); - AuraEffect healingIncreaseEffect = unit.GetAuraEffect(bonusSpellId, effIndex); - if (healingIncreaseEffect != null) - return healingIncreaseEffect.GetAmount(); + return true; + }); + } + } - return SpellMgr.GetSpellInfo(bonusSpellId, Difficulty.None).GetEffect(effIndex).CalcValue(unit); + GameObject GetControlZone() + { + Unit caster = GetCaster(); + if (caster != null) + { + var auraEffects = caster.GetAuraEffectsByType(AuraType.ActAsControlZone); + foreach (AuraEffect auraEffect in auraEffects) + { + GameObject gameobject = caster.GetGameObject(auraEffect.GetSpellInfo().Id); + if (gameobject != null) + return gameobject; } - - return 0.0f; } + + return null; } - // 157982 - Tranquility (Heal) - // 64844 - Divine Hymn (Heal) - // 114942 - Healing Tide (Heal) - [Script] // 115310 - Revival (Heal) - class spell_gen_major_healing_cooldown_modifier : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect - ( - (MajorPlayerHealingCooldownHelpers.SpellDruidTranquility, 2), - (MajorPlayerHealingCooldownHelpers.SpellPriestDivineHymn, 1), - (MajorPlayerHealingCooldownHelpers.SpellShamanHealingTideTotem, 2), - (MajorPlayerHealingCooldownHelpers.SpellMonkRevival, 4) - ); - } - - void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) - { - MathFunctions.AddPct(ref pctMod, MajorPlayerHealingCooldownHelpers.GetBonusMultiplier(GetCaster(), GetSpellInfo().Id)); - } - - public override void Register() - { - CalcHealing.Add(new(CalculateHealingBonus)); - } + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaAlly)); } +} - // 157982 - Tranquility (Heal) - // 271466 - Luminous Barrier (Absorb) - [Script] // 363534 - Rewind (Heal) - class spell_gen_major_healing_cooldown_modifier_AuraScript : AuraScript +[Script] // 128648 - Defending Cart Aura +class spell_bg_defending_cart_aura_AuraScript : AuraScript +{ + void OnPeriodic(AuraEffect aurEff) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect - ( - (MajorPlayerHealingCooldownHelpers.SpellDruidTranquility, 2), - (MajorPlayerHealingCooldownHelpers.SpellPriestLuminousBarrier, 1), - (MajorPlayerHealingCooldownHelpers.SpellEvokerRewind, 3) - ); - } + Unit caster = GetCaster(); + if (caster == null) + return; - void CalculateHealingBonus(AuraEffect aurEff, Unit victim, ref int damageOrHealing, ref int flatMod, ref float pctMod) - { - Unit caster = GetCaster(); - if (caster != null) - MathFunctions.AddPct(ref pctMod, MajorPlayerHealingCooldownHelpers.GetBonusMultiplier(caster, GetSpellInfo().Id)); - } - - public override void Register() - { - DoEffectCalcDamageAndHealing.Add(new(CalculateHealingBonus, SpellConst.EffectAll, AuraType.Any)); - } + GameObject controlZone = GetControlZone(); + if (controlZone != null && !controlZone.GetInsidePlayers().Contains(GetTarget().GetGUID())) + GetTarget().RemoveAurasDueToSpell(GetSpellInfo().Id, caster.GetGUID()); } - // 24931 - 100 Health - // 24959 - 500 Health - // 28838 - 1 Health - // 43645 - 1 Health - // 73342 - 1 Health - [Script] // 86562 - 1 Health - class spell_gen_set_health : SpellScript + GameObject GetControlZone() { - ulong _health; - - public spell_gen_set_health(ulong health) + Unit caster = GetCaster(); + if (caster != null) { - _health = health; + var auraEffects = caster.GetAuraEffectsByType(AuraType.ActAsControlZone); + foreach (AuraEffect auraEffect in auraEffects) + { + GameObject gameobject = caster.GetGameObject(auraEffect.GetSpellInfo().Id); + if (gameobject != null) + return gameobject; + } } - void HandleHit(uint effIndex) - { - if (GetHitUnit().IsAlive() && _health > 0) - GetHitUnit().SetHealth(_health); - } - - public override void Register() - { - OnEffectHitTarget.Add(new EffectHandler(HandleHit, 0, SpellEffectName.ScriptEffect)); - } + return null; } - [Script] // 296837 - Comfortable Rider's Barding - class spell_gen_comfortable_riders_barding : AuraScript + public override void Register() { - static uint SPELL_DAZED = 1604; - - bool _apply; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SPELL_DAZED); - } - - void HandleEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().ApplySpellImmune(GetId(), SpellImmunity.Id, SPELL_DAZED, _apply); - } - - public override void Register() - { - _apply = true; - OnEffectApply.Add(new EffectApplyHandler(HandleEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - _apply = false; - OnEffectRemove.Add(new EffectApplyHandler(HandleEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.PeriodicDummy)); } +} - [Script] // 297091 - Parachute - class spell_gen_saddlechute : AuraScript +[Script] // 296837 - Comfortable Rider's Barding +class spell_gen_comfortable_riders_barding : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) { - static uint SPELL_PARACHUTE = 297092; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SPELL_PARACHUTE); - } - - void TriggerParachute(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - if (target.IsFlying() || target.IsFalling()) - target.CastSpell(target, SPELL_PARACHUTE, new CastSpellExtraArgs(TriggerCastFlags.DontReportCastError)); - } - - public override void Register() - { - AfterEffectRemove.Add(new EffectApplyHandler(TriggerParachute, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + return ValidateSpellInfo(1604); } -} \ No newline at end of file + + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().ApplySpellImmune(GetId(), SpellImmunity.Id, 1604, true); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().ApplySpellImmune(GetId(), SpellImmunity.Id, 1604, false); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 297091 - Parachute +class spell_gen_saddlechute : AuraScript +{ + static uint SpellParachute = 297092; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellParachute); + } + + void TriggerParachute(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + if (target.IsFlying() || target.IsFalling()) + target.CastSpell(target, SpellParachute, TriggerCastFlags.DontReportCastError); + } + + public override void Register() + { + AfterEffectRemove.Add(new(TriggerParachute, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 257040 - Spatial Rift +class spell_gen_spatial_rift : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SpatialRiftTeleport, SpellIds.SpatialRiftAreatrigger); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + + AreaTrigger at = caster.GetAreaTrigger(SpellIds.SpatialRiftAreatrigger); + if (at == null) + return; + + caster.CastSpell(at.GetPosition(), SpellIds.SpatialRiftTeleport, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + + at.SetDuration(0); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class at_gen_spatial_rift(AreaTrigger areatrigger) : AreaTriggerAI(areatrigger) +{ + public override void OnInitialize() + { + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(at.GetSpellId(), Difficulty.None); + if (spellInfo == null) + return; + + Position destPos = at.GetPosition(); + at.MovePositionToFirstCollision(destPos, spellInfo.GetMaxRange(), 0.0f); + + PathGenerator path = new(at); + path.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), true); + + at.InitSplines(path.GetPath()); + } +} + +[Script] +class spell_gen_force_phase_update : AuraScript +{ + void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + PhasingHandler.OnConditionChange(GetTarget()); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + PhasingHandler.OnConditionChange(GetTarget()); + } + + public override void Register() + { + AfterEffectApply.Add(new(AfterApply, SpellConst.EffectFirstFound, AuraType.Any, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, SpellConst.EffectFirstFound, AuraType.Any, AuraEffectHandleModes.Real)); + } +} + +[Script("spell_gen_no_npc_damage_below_override_70", 70.0f)] +class spell_gen_no_npc_damage_below_override(float healthPct) : AuraScript +{ + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + amount = -1; + } + + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + if (dmgInfo.GetAttacker() == null || !dmgInfo.GetAttacker().IsCreature()) + { + PreventDefaultAction(); + return; + } + + if (GetTarget().GetHealthPct() <= healthPct) + absorbAmount = dmgInfo.GetDamage(); + else + PreventDefaultAction(); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + } +} + +[Script] // 92678 - Abandon Vehicle +class spell_gen_abandon_vehicle : SpellScript +{ + void HandleHitTarget(uint effIndex) + { + GetHitUnit().ExitVehicle(); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHitTarget, SpellConst.EffectFirstFound, SpellEffectName.ScriptEffect)); + } +} diff --git a/Source/Scripts/Spells/Hunter.cs b/Source/Scripts/Spells/Hunter.cs index b67859f83..32ca94ded 100644 --- a/Source/Scripts/Spells/Hunter.cs +++ b/Source/Scripts/Spells/Hunter.cs @@ -1,769 +1,1430 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; +using Framework.Dynamic; +using Game.AI; using Game.Entities; using Game.Scripting; using Game.Spells; using System; -using static Global; +using System.Linq; -namespace Scripts.Spells.Hunter +namespace Scripts.Spells.Hunter; + +struct SpellIds { - struct SpellIds + public const uint AMurderOfCrowsDamage = 131900; + public const uint AMurderOfCrowsVisual1 = 131637; + public const uint AMurderOfCrowsVisual2 = 131951; + public const uint AMurderOfCrowsVisual3 = 131952; + public const uint AimedShot = 19434; + public const uint AspectCheetahSlow = 186258; + public const uint AspectOfTheFox = 1219162; + public const uint AspectOfTheTurtlePacifyAura = 205769; + public const uint BindingShot = 109248; + public const uint BindingShotImmune = 117553; + public const uint BindingShotMarker = 117405; + public const uint BindingShotStun = 117526; + public const uint BindingShotVisual = 117614; + public const uint BindingShotVisualArrow = 118306; + public const uint ConcussiveShot = 5116; + public const uint EmergencySalveTalent = 459517; + public const uint EmergencySalveDispel = 459521; + public const uint EntrapmentTalent = 393344; + public const uint EntrapmentRoot = 393456; + public const uint Exhilaration = 109304; + public const uint ExhilarationPet = 128594; + public const uint ExhilarationR2 = 231546; + public const uint ExplosiveShotDamage = 212680; + public const uint GreviousInjury = 1217789; + public const uint HighExplosiveTrap = 236775; + public const uint HighExplosiveTrapDamage = 236777; + public const uint ImplosiveTrap = 462032; + public const uint ImplosiveTrapDamage = 462033; + public const uint Intimidation = 19577; + public const uint IntimidationMarksmanship = 474421; + public const uint LatentPoisonStack = 378015; + public const uint LatentPoisonDamage = 378016; + public const uint LatentPoisonInjectorsStack = 336903; + public const uint LatentPoisonInjectorsDamage = 336904; + public const uint LockAndLoad = 194594; + public const uint LoneWolf = 155228; + public const uint MarksmanshipHunterAura = 137016; + public const uint MasterMarksman = 269576; + public const uint MastersCallTriggered = 62305; + public const uint Misdirection = 34477; + public const uint MisdirectionProc = 35079; + public const uint MultiShotFocus = 213363; + public const uint PetLastStandTriggered = 53479; + public const uint PetHeartOfThePhoenixTriggered = 54114; + public const uint PetHeartOfThePhoenixDebuff = 55711; + public const uint PosthasteIncreaseSpeed = 118922; + public const uint PosthasteTalent = 109215; + public const uint PreciseShots = 260242; + public const uint RapidFire = 257044; + public const uint RapidFireDamage = 257045; + public const uint RapidFireEnergize = 263585; + public const uint RejuvenatingWindHeal = 385540; + public const uint ScoutsInstincts = 459455; + public const uint ShrapnelShotTalent = 473520; + public const uint ShrapnelShotDebuff = 474310; + public const uint SteadyShot = 56641; + public const uint SteadyShotFocus = 77443; + public const uint StreamlineTalent = 260367; + public const uint StreamlineBuff = 342076; + public const uint T9_4PGreatness = 68130; + public const uint T29_2PMarksmanshipDamage = 394371; + public const uint TarTrap = 187699; + public const uint TarTrapAreatrigger = 187700; + public const uint TarTrapSlow = 135299; + public const uint WildernessMedicineTalent = 343242; + public const uint WildernessMedicineDispel = 384784; + public const uint RoarOfSacrificeTriggered = 67481; + + public const uint DraeneiGiftOfTheNaaru = 59543; +} + +[Script] // 131894 - A Murder of Crows +class spell_hun_a_murder_of_crows : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) { - public const uint AMurderOfCrowsDamage = 131900; - public const uint AMurderOfCrowsVisual1 = 131637; - public const uint AMurderOfCrowsVisual2 = 131951; - public const uint AMurderOfCrowsVisual3 = 131952; - public const uint AspectCheetahSlow = 186258; - public const uint AspectOfTheTurtlePacifyAura = 205769; - public const uint Exhilaration = 109304; - public const uint ExhilarationPet = 128594; - public const uint ExhilarationR2 = 231546; - public const uint ExplosiveShotDamage = 212680; - public const uint LatentPoisonStack = 378015; - public const uint LatentPoisonDamage = 378016; - public const uint LatentPoisonInjectorsStack = 336903; - public const uint LatentPoisonInjectorsDamage = 336904; - public const uint LoneWolf = 155228; - public const uint MastersCallTriggered = 62305; - public const uint Misdirection = 34477; - public const uint MisdirectionProc = 35079; - public const uint MultiShotFocus = 213363; - public const uint PetLastStandTriggered = 53479; - public const uint PetHeartOfThePhoenixTriggered = 54114; - public const uint PetHeartOfThePhoenixDebuff = 55711; - public const uint PosthasteIncreaseSpeed = 118922; - public const uint PosthasteTalent = 109215; - public const uint RapidFireDamage = 257045; - public const uint RapidFireEnergize = 263585; - public const uint SteadyShotFocus = 77443; - public const uint T94PGreatness = 68130; - public const uint T292PMarksmanshipDamage = 394371; - public const uint RoarOfSacrificeTriggered = 67481; - public const uint DraeneiGiftOfTheNaaru = 59543; + return ValidateSpellInfo(SpellIds.AMurderOfCrowsDamage, SpellIds.AMurderOfCrowsVisual1, SpellIds.AMurderOfCrowsVisual2, SpellIds.AMurderOfCrowsVisual3); } - [Script] // 131894 - A Murder of Crows - class spell_hun_a_murder_of_crows : AuraScript + void HandleDummyTick(AuraEffect aurEff) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AMurderOfCrowsDamage, SpellIds.AMurderOfCrowsVisual1, SpellIds.AMurderOfCrowsVisual2, SpellIds.AMurderOfCrowsVisual3); - } + Unit target = GetTarget(); - void HandleDummyTick(AuraEffect aurEff) - { - Unit target = GetTarget(); + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(target, SpellIds.AMurderOfCrowsDamage, true); - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(target, SpellIds.AMurderOfCrowsDamage, true); - - target.CastSpell(target, SpellIds.AMurderOfCrowsVisual1, true); - target.CastSpell(target, SpellIds.AMurderOfCrowsVisual2, true); - target.CastSpell(target, SpellIds.AMurderOfCrowsVisual3, true); - target.CastSpell(target, SpellIds.AMurderOfCrowsVisual3, true); // not a mistake, it is intended to cast twice - } - - void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Death) - { - Unit caster = GetCaster(); - if (caster != null) - caster.GetSpellHistory().ResetCooldown(GetId(), true); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy)); - OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); - } + target.CastSpell(target, SpellIds.AMurderOfCrowsVisual1, true); + target.CastSpell(target, SpellIds.AMurderOfCrowsVisual2, true); + target.CastSpell(target, SpellIds.AMurderOfCrowsVisual3, true); + target.CastSpell(target, SpellIds.AMurderOfCrowsVisual3, true); // not a mistake, it is intended to cast twice } - [Script] // 186257 - Aspect of the Cheetah - class spell_hun_aspect_cheetah : AuraScript + void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AspectCheetahSlow); - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) - GetTarget().CastSpell(GetTarget(), SpellIds.AspectCheetahSlow, true); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.ModIncreaseSpeed, AuraEffectHandleModes.Real)); - } - } - - [Script] // 186265 - Aspect of the Turtle - class spell_hun_aspect_of_the_turtle : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AspectOfTheTurtlePacifyAura); - } - - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().CastSpell(GetTarget(), SpellIds.AspectOfTheTurtlePacifyAura, true); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.AspectOfTheTurtlePacifyAura); - } - - public override void Register() - { - AfterEffectApply.Add(new EffectApplyHandler(OnApply, 0, AuraType.ModAttackerMeleeHitChance, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.ModAttackerMeleeHitChance, AuraEffectHandleModes.Real)); - } - } - - [Script] // 378750 - Cobra Sting - class spell_hun_cobra_sting : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - bool RollProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - return RandomHelper.randChance(GetEffect(1).GetAmount()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(RollProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 109304 - Exhilaration - class spell_hun_exhilaration : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ExhilarationR2, SpellIds.LoneWolf); - } - - void HandleOnHit() - { - if (GetCaster().HasAura(SpellIds.ExhilarationR2) && !GetCaster().HasAura(SpellIds.LoneWolf)) - GetCaster().CastSpell(null, SpellIds.ExhilarationPet, true); - } - - public override void Register() - { - OnHit.Add(new(HandleOnHit)); - } - } - - [Script] // 212431 - Explosive Shot - class spell_hun_explosive_shot : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ExplosiveShotDamage); - } - - void HandlePeriodic(AuraEffect aurEff) + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Death) { Unit caster = GetCaster(); if (caster != null) - caster.CastSpell(GetTarget(), SpellIds.ExplosiveShotDamage, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDummy)); + caster.GetSpellHistory().ResetCooldown(GetId(), true); } } - [Script] // 212658 - Hunting Party - class spell_hun_hunting_party : AuraScript + + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Exhilaration, SpellIds.ExhilarationPet); - } + OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy)); + OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.Exhilaration, -TimeSpan.FromSeconds(aurEff.GetAmount())); - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.ExhilarationPet, -TimeSpan.FromSeconds(aurEff.GetAmount())); - } +[Script] // 186257 - Aspect of the Cheetah +class spell_hun_aspect_cheetah : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AspectCheetahSlow); + } - public override void Register() + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) + GetTarget().CastSpell(GetTarget(), SpellIds.AspectCheetahSlow, true); + } + + + public override void Register() + { + AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.ModIncreaseSpeed, AuraEffectHandleModes.Real)); + } +} + +[Script] // 1219162 - Aspect of the Fox (attached to 186257 - Aspect of the Cheetah) +class spell_hun_aspect_of_the_fox : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AspectOfTheFox) + && ValidateSpellEffect((spellInfo.Id, 2)) + && spellInfo.GetEffect(2).IsAura(AuraType.CastWhileWalking); + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.AspectOfTheFox); + } + + static void HandleCastWhileWalking(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(HandleCastWhileWalking, 2, Targets.UnitCaster)); + } +} + +[Script] // 186265 - Aspect of the Turtle +class spell_hun_aspect_of_the_turtle : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AspectOfTheTurtlePacifyAura); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().CastSpell(GetTarget(), SpellIds.AspectOfTheTurtlePacifyAura, true); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.AspectOfTheTurtlePacifyAura); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnApply, 0, AuraType.ModAttackerMeleeHitChance, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.ModAttackerMeleeHitChance, AuraEffectHandleModes.Real)); + } +} + +[Script] // 109248 - Binding Shot +class spell_hun_binding_shot : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BindingShotVisualArrow); + } + + void HandleCast() + { + GetCaster().CastSpell(GetExplTargetDest().GetPosition(), SpellIds.BindingShotVisualArrow, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + + public override void Register() + { + OnCast.Add(new(HandleCast)); + } +} + +// 109248 - Binding Shot +[Script] // Id - 1524 +class at_hun_binding_shot(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TaskScheduler _scheduler = new(); + + public override void OnInitialize() + { + Unit caster = at.GetCaster(); + if (caster != null) { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + foreach (AreaTrigger other in caster.GetAreaTriggers(SpellIds.BindingShot)) + other.SetDuration(0); } } - [Script] // 53478 - Last Stand Pet - class spell_hun_last_stand_pet : SpellScript + public override void OnCreate(Spell creatingSpell) { - public override bool Validate(SpellInfo spellInfo) + _scheduler.Schedule(TimeSpan.FromSeconds(1), task => { - return ValidateSpellInfo(SpellIds.PetLastStandTriggered); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)caster.CountPctFromMaxHealth(30)); - caster.CastSpell(caster, SpellIds.PetLastStandTriggered, args); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 378016 - Latent Poison - class spell_hun_latent_poison_damage : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LatentPoisonStack); - } - - void CalculateDamage() - { - Aura stack = GetHitUnit().GetAura(SpellIds.LatentPoisonStack, GetCaster().GetGUID()); - if (stack != null) + foreach (ObjectGuid guid in at.GetInsideUnits()) { - SetHitDamage(GetHitDamage() * stack.GetStackAmount()); - stack.Remove(); + Unit unit = Global.ObjAccessor.GetUnit(at, guid); + if (!unit.HasAura(SpellIds.BindingShotMarker)) + continue; + + unit.CastSpell(at.GetPosition(), SpellIds.BindingShotVisual, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + + task.Repeat(); + }); + } + + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (caster.IsValidAttackTarget(unit) && !unit.HasAura(SpellIds.BindingShotImmune, caster.GetGUID())) + { + caster.CastSpell(unit, SpellIds.BindingShotMarker, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + unit.CastSpell(at.GetPosition(), SpellIds.BindingShotVisual, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); } } - - public override void Register() - { - OnHit.Add(new(CalculateDamage)); - } } - // 19434 - Aimed Shot - // 186270 - Raptor Strike - // 217200 - Barbed Shot - [Script] // 259387 - Mongoose Bite - class spell_hun_latent_poison_trigger : SpellScript + public override void OnUnitExit(Unit unit) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LatentPoisonStack, SpellIds.LatentPoisonDamage); - } + unit.RemoveAurasDueToSpell(SpellIds.BindingShotMarker, at.GetCasterGUID()); - void TriggerDamage() - { - if (GetHitUnit().HasAura(SpellIds.LatentPoisonStack, GetCaster().GetGUID())) - GetCaster().CastSpell(GetHitUnit(), SpellIds.LatentPoisonDamage, GetSpell()); - } + if (at.IsRemoved()) + return; - public override void Register() + Unit caster = at.GetCaster(); + if (caster != null) { - AfterHit.Add(new(TriggerDamage)); - } - } - - [Script] // 336904 - Latent Poison Injectors - class spell_hun_latent_poison_injectors_damage : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LatentPoisonInjectorsStack); - } - - void CalculateDamage() - { - Aura stack = GetHitUnit().GetAura(SpellIds.LatentPoisonInjectorsStack, GetCaster().GetGUID()); - if (stack != null) + if (caster.IsValidAttackTarget(unit) && !unit.HasAura(SpellIds.BindingShotImmune, caster.GetGUID())) { - SetHitDamage(GetHitDamage() * stack.GetStackAmount()); - stack.Remove(); + caster.CastSpell(unit, SpellIds.BindingShotStun, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + caster.CastSpell(unit, SpellIds.BindingShotImmune, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); } } + } - public override void Register() + public override void OnUpdate(uint diff) + { + _scheduler.Update(diff); + } +} + +[Script] // 204089 - Bullseye +class spell_hun_bullseye : AuraScript +{ + static bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActionTarget().HealthBelowPct(aurEff.GetAmount()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 378750 - Cobra Sting +class spell_hun_cobra_sting : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + bool RollProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + return RandomHelper.randChance(GetEffect(1).GetAmount()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(RollProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 5116 - Concussive Shot (attached to 193455 - Cobra Shot and 56641 - Steady Shot) +class spell_hun_concussive_shot : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ConcussiveShot) + && ValidateSpellEffect((SpellIds.SteadyShot, 2)); + } + + void HandleDuration(uint effIndex) + { + Unit caster = GetCaster(); + + Aura concussiveShot = GetHitUnit().GetAura(SpellIds.ConcussiveShot, caster.GetGUID()); + if (concussiveShot != null) { - OnHit.Add(new(CalculateDamage)); + SpellInfo steadyShot = Global.SpellMgr.GetSpellInfo(SpellIds.SteadyShot, GetCastDifficulty()); + TimeSpan extraDuration = TimeSpan.FromSeconds(steadyShot.GetEffect(2).CalcValue(caster) / 10); + TimeSpan newDuration = TimeSpan.FromSeconds(concussiveShot.GetDuration()) + extraDuration; + concussiveShot.SetDuration((int)newDuration.TotalMicroseconds); + concussiveShot.SetMaxDuration((int)newDuration.TotalMicroseconds); } } - // 186270 - Raptor Strike - [Script] // 259387 - Mongoose Bite - class spell_hun_latent_poison_injectors_trigger : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LatentPoisonInjectorsStack, SpellIds.LatentPoisonInjectorsDamage); - } + OnEffectHitTarget.Add(new(HandleDuration, SpellConst.EffectFirstFound, SpellEffectName.SchoolDamage)); + } +} - void TriggerDamage() - { - if (GetHitUnit().HasAura(SpellIds.LatentPoisonInjectorsStack, GetCaster().GetGUID())) - GetCaster().CastSpell(GetHitUnit(), SpellIds.LatentPoisonInjectorsDamage, GetSpell()); - } +[Script] // 459517 - Concussive Shot (attached to 186265 - Aspect of the Turtle and 5384 - Feign Death) +class spell_hun_emergency_salve : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EmergencySalveTalent, SpellIds.EmergencySalveDispel); + } - public override void Register() + public override bool Load() + { + return GetCaster().HasAura(SpellIds.EmergencySalveTalent); + } + + void HandleAfterCast() + { + GetCaster().CastSpell(GetCaster(), SpellIds.EmergencySalveDispel, new CastSpellExtraArgs() { - AfterHit.Add(new(TriggerDamage)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 109304 - Exhilaration +class spell_hun_exhilaration : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ExhilarationR2, SpellIds.LoneWolf); + } + + void HandleOnHit() + { + if (GetCaster().HasAura(SpellIds.ExhilarationR2) && !GetCaster().HasAura(SpellIds.LoneWolf)) + GetCaster().CastSpell(null, SpellIds.ExhilarationPet, true); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] // 212431 - Explosive Shot +class spell_hun_explosive_shot : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ExplosiveShotDamage); + } + + void HandlePeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.ExplosiveShotDamage, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDummy)); + } +} + +// 236775 - High Explosive Trap +[Script] // 9810 - AreatriggerId +class areatrigger_hun_high_explosive_trap(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnInitialize() + { + Unit caster = at.GetCaster(); + if (caster != null) + { + foreach (AreaTrigger other in caster.GetAreaTriggers(SpellIds.HighExplosiveTrap)) + other.SetDuration(0); } } - [Script] // 53271 - Masters Call - class spell_hun_masters_call : SpellScript + public override void OnUnitEnter(Unit unit) { - public override bool Validate(SpellInfo spellInfo) + Unit caster = at.GetCaster(); + if (caster != null) { - return ValidateSpellEffect((spellInfo.Id, 0)) - && ValidateSpellInfo(SpellIds.MastersCallTriggered, (uint)spellInfo.GetEffect(0).CalcValue()); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - SpellCastResult DoCheckCast() - { - Guardian pet = GetCaster().ToPlayer().GetGuardianPet(); - Cypher.Assert(pet != null); // checked in Spell.CheckCast - - if (!pet.IsPet() || !pet.IsAlive()) - return SpellCastResult.NoPet; - - // Do a mini Spell.CheckCasterAuras on the pet, no other way of doing this - SpellCastResult result = SpellCastResult.SpellCastOk; - UnitFlags unitflag = (UnitFlags)(uint)pet.m_unitData.Flags; - if (!pet.GetCharmerGUID().IsEmpty()) - result = SpellCastResult.Charmed; - else if (unitflag.HasFlag(UnitFlags.Stunned)) - result = SpellCastResult.Stunned; - else if (unitflag.HasFlag(UnitFlags.Fleeing)) - result = SpellCastResult.Fleeing; - else if (unitflag.HasFlag(UnitFlags.Confused)) - result = SpellCastResult.Confused; - - if (result != SpellCastResult.SpellCastOk) - return result; - - Unit target = GetExplTargetUnit(); - if (target == null) - return SpellCastResult.BadTargets; - - if (!pet.IsWithinLOSInMap(target)) - return SpellCastResult.LineOfSight; - - return SpellCastResult.SpellCastOk; - } - - void HandleDummy(uint effIndex) - { - GetCaster().ToPlayer().GetPet().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); - } - - void HandleScriptEffect(uint effIndex) - { - GetHitUnit().CastSpell(null, SpellIds.MastersCallTriggered, true); - } - - public override void Register() - { - OnCheckCast.Add(new(DoCheckCast)); - - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 34477 - Misdirection - class spell_hun_misdirection : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MisdirectionProc); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Default || GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Interrupt) - return; - - if (!GetTarget().HasAura(SpellIds.MisdirectionProc)) - GetTarget().GetThreatManager().UnregisterRedirectThreat(SpellIds.Misdirection); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellIds.MisdirectionProc, aurEff); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - } - - [Script] // 35079 - Misdirection (Proc) - class spell_hun_misdirection_proc : AuraScript - { - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().GetThreatManager().UnregisterRedirectThreat(SpellIds.Misdirection); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 2643 - Multi-Shot - class spell_hun_multi_shot : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MultiShotFocus); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleOnHit() - { - // We need to check hunter's spec because it doesn't generate focus on other specs than Mm - if (GetCaster().ToPlayer().GetPrimarySpecialization() == ChrSpecialization.HunterMarksmanship) - GetCaster().CastSpell(GetCaster(), SpellIds.MultiShotFocus, true); - } - - public override void Register() - { - OnHit.Add(new(HandleOnHit)); - } - } - - [Script] // 55709 - Pet Heart of the Phoenix - class spell_hun_pet_heart_of_the_phoenix : SpellScript - { - public override bool Load() - { - if (!GetCaster().IsPet()) - return false; - return true; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PetHeartOfThePhoenixTriggered, SpellIds.PetHeartOfThePhoenixDebuff); - } - - void HandleScript(uint effIndex) - { - Unit caster = GetCaster(); - Unit owner = caster.GetOwner(); - if (owner != null) + if (caster.IsValidAttackTarget(unit)) { - if (!caster.HasAura(SpellIds.PetHeartOfThePhoenixDebuff)) - { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, 100); - owner.CastSpell(caster, SpellIds.PetHeartOfThePhoenixTriggered, args); - caster.CastSpell(caster, SpellIds.PetHeartOfThePhoenixDebuff, true); - } + caster.CastSpell(at.GetPosition(), SpellIds.HighExplosiveTrapDamage, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + at.Remove(); } } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 781 - Disengage - class spell_hun_posthaste : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PosthasteTalent, SpellIds.PosthasteIncreaseSpeed); - } - - void HandleAfterCast() - { - if (GetCaster().HasAura(SpellIds.PosthasteTalent)) - { - GetCaster().RemoveMovementImpairingAuras(true); - GetCaster().CastSpell(GetCaster(), SpellIds.PosthasteIncreaseSpeed, GetSpell()); - } - } - - public override void Register() - { - AfterCast.Add(new(HandleAfterCast)); - } - } - - [Script] // 257044 - Rapid Fire - class spell_hun_rapid_fire : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RapidFireDamage); - } - - void HandlePeriodic(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(GetTarget(), SpellIds.RapidFireDamage, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodic, 1, AuraType.PeriodicDummy)); - } - } - - [Script] // 257045 - Rapid Fire Damage - class spell_hun_rapid_fire_damage : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RapidFireEnergize); - } - - void HandleHit(uint effIndex) - { - GetCaster().CastSpell(null, SpellIds.RapidFireEnergize, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); - } - } - - [Script] // 53480 - Roar of Sacrifice - class spell_hun_roar_of_sacrifice : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RoarOfSacrificeTriggered); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || (damageInfo.GetSchoolMask() & (SpellSchoolMask)aurEff.GetMiscValue()) == 0) - return false; - - if (GetCaster() == null) - return false; - - return true; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), aurEff.GetAmount())); - eventInfo.GetActor().CastSpell(GetCaster(), SpellIds.RoarOfSacrificeTriggered, args); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 1, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - } - - [Script] // 37506 - Scatter Shot - class spell_hun_scatter_shot : SpellScript - { - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - // break var Shot and autohit - caster.InterruptSpell(CurrentSpellTypes.AutoRepeat); - caster.AttackStop(); - caster.SendAttackSwingCancelAttack(); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 56641 - Steady Shot - class spell_hun_steady_shot : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SteadyShotFocus); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleOnHit() - { - GetCaster().CastSpell(GetCaster(), SpellIds.SteadyShotFocus, true); - } - - public override void Register() - { - OnHit.Add(new(HandleOnHit)); - } - } - - [Script] // 1515 - Tame Beast - class spell_hun_tame_beast : SpellScript - { - uint[] CallPetSpellIds = { 883, 83242, 83243, 83244, 83245, }; - - SpellCastResult CheckCast() - { - Player caster = GetCaster().ToPlayer(); - if (caster == null) - return SpellCastResult.DontReport; - - if (GetExplTargetUnit() == null) - return SpellCastResult.BadImplicitTargets; - - Creature target = GetExplTargetUnit().ToCreature(); - if (target != null) - { - if (target.GetLevelForTarget(caster) > caster.GetLevel()) - return SpellCastResult.Highlevel; - - // use SmsgPetTameFailure? - if (!target.GetCreatureTemplate().IsTameable(caster.CanTameExoticPets(), target.GetCreatureDifficulty())) - return SpellCastResult.BadTargets; - - PetStable petStable = caster.GetPetStable(); - if (petStable != null) - { - if (petStable.CurrentPetIndex.HasValue) - return SpellCastResult.AlreadyHaveSummon; - - var freeSlotIndex = Array.FindIndex(petStable.ActivePets, petInfo => petInfo == null); - if (freeSlotIndex == -1) - { - caster.SendTameFailure(PetTameResult.TooMany); - return SpellCastResult.DontReport; - } - - // Check for known Call Pet X spells - if (!caster.HasSpell(CallPetSpellIds[freeSlotIndex])) - { - caster.SendTameFailure(PetTameResult.TooMany); - return SpellCastResult.DontReport; - } - } - - if (!caster.GetCharmedGUID().IsEmpty()) - return SpellCastResult.AlreadyHaveCharm; - - if (!target.GetOwnerGUID().IsEmpty()) - { - caster.SendTameFailure(PetTameResult.CreatureAlreadyOwned); - return SpellCastResult.DontReport; - } - } - else - return SpellCastResult.BadImplicitTargets; - - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - } - } - - [Script] // 67151 - Item - Hunter T9 4P Bonus (Steady Shot) - class spell_hun_t9_4p_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.T94PGreatness); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - if (eventInfo.GetActor().IsPlayer() && eventInfo.GetActor().ToPlayer().GetPet() != null) - return true; - return false; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - - caster.CastSpell(caster.ToPlayer().GetPet(), SpellIds.T94PGreatness, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 394366 - Find The Mark - class spell_hun_t29_2p_marksmanship_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.T292PMarksmanshipDamage, 0)) - && SpellMgr.GetSpellInfo(SpellIds.T292PMarksmanshipDamage, Difficulty.None).GetMaxTicks() != 0; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActor(); - uint ticks = SpellMgr.GetSpellInfo(SpellIds.T292PMarksmanshipDamage, Difficulty.None).GetMaxTicks(); - uint damage = MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetOriginalDamage(), aurEff.GetAmount()) / ticks; - - caster.CastSpell(eventInfo.GetActionTarget(), SpellIds.T292PMarksmanshipDamage, new CastSpellExtraArgs(aurEff) - .SetTriggeringSpell(eventInfo.GetProcSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, (int)damage)); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } } } + +[Script] // 212658 - Hunting Party +class spell_hun_hunting_party : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Exhilaration, SpellIds.ExhilarationPet); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.Exhilaration, -TimeSpan.FromSeconds(aurEff.GetAmount())); + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.ExhilarationPet, -TimeSpan.FromSeconds(aurEff.GetAmount())); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// 462032 - Implosive Trap +[Script] // 34378 - AreatriggerId +class areatrigger_hun_implosive_trap(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnInitialize() + { + Unit caster = at.GetCaster(); + if (caster != null) + { + foreach (AreaTrigger other in caster.GetAreaTriggers(SpellIds.ImplosiveTrap)) + other.SetDuration(0); + } + } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (caster.IsValidAttackTarget(unit)) + { + caster.CastSpell(at.GetPosition(), SpellIds.ImplosiveTrapDamage, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + at.Remove(); + } + } + } +} + +[Script] // 53478 - Last Stand Pet +class spell_hun_last_stand_pet : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PetLastStandTriggered); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)caster.CountPctFromMaxHealth(30)); + caster.CastSpell(caster, SpellIds.PetLastStandTriggered, args); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 378016 - Latent Poison +class spell_hun_latent_poison_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LatentPoisonStack); + } + + void CalculateDamage() + { + Aura stack = GetHitUnit().GetAura(SpellIds.LatentPoisonStack, GetCaster().GetGUID()); + if (stack != null) + { + SetHitDamage(GetHitDamage() * stack.GetStackAmount()); + stack.Remove(); + } + } + + public override void Register() + { + OnHit.Add(new(CalculateDamage)); + } +} + +// 19434 - Aimed Shot +// 186270 - Raptor Strike +// 217200 - Barbed Shot +[Script] // 259387 - Mongoose Bite +class spell_hun_latent_poison_trigger : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LatentPoisonStack, SpellIds.LatentPoisonDamage); + } + + void TriggerDamage() + { + if (GetHitUnit().HasAura(SpellIds.LatentPoisonStack, GetCaster().GetGUID())) + GetCaster().CastSpell(GetHitUnit(), SpellIds.LatentPoisonDamage, GetSpell()); + } + + public override void Register() + { + AfterHit.Add(new(TriggerDamage)); + } +} + +[Script] // 336904 - Latent Poison Injectors +class spell_hun_latent_poison_injectors_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LatentPoisonInjectorsStack); + } + + void CalculateDamage() + { + Aura stack = GetHitUnit().GetAura(SpellIds.LatentPoisonInjectorsStack, GetCaster().GetGUID()); + if (stack != null) + { + SetHitDamage(GetHitDamage() * stack.GetStackAmount()); + stack.Remove(); + } + } + + public override void Register() + { + OnHit.Add(new(CalculateDamage)); + } +} + +// 186270 - Raptor Strike +[Script] // 259387 - Mongoose Bite +class spell_hun_latent_poison_injectors_trigger : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LatentPoisonInjectorsStack, SpellIds.LatentPoisonInjectorsDamage); + } + + void TriggerDamage() + { + if (GetHitUnit().HasAura(SpellIds.LatentPoisonInjectorsStack, GetCaster().GetGUID())) + GetCaster().CastSpell(GetHitUnit(), SpellIds.LatentPoisonInjectorsDamage, GetSpell()); + } + + public override void Register() + { + AfterHit.Add(new(TriggerDamage)); + } +} + +[Script] // 1217788 - Manhunter +class spell_hun_manhunter : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GreviousInjury); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget().IsPlayer(); + } + + static void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.GreviousInjury, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 260309 - Master Marksman +class spell_hun_master_marksman : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MasterMarksman); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + uint ticks = Global.SpellMgr.GetSpellInfo(SpellIds.MasterMarksman, Difficulty.None).GetMaxTicks(); + if (ticks == 0) + return; + + int damage = (int)(MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), aurEff.GetAmount()) / ticks); + + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.MasterMarksman, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, damage) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 53271 - Masters Call +class spell_hun_masters_call : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 0)) + && ValidateSpellInfo(SpellIds.MastersCallTriggered, (uint)spellInfo.GetEffect(0).CalcValue()); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + SpellCastResult DoCheckCast() + { + Guardian pet = GetCaster().ToPlayer().GetGuardianPet(); + Cypher.Assert(pet != null); // checked in Spell::CheckCast + + if (!pet.IsPet() || !pet.IsAlive()) + return SpellCastResult.NoPet; + + // Do a mini Spell::CheckCasterAuras on the pet, no other way of doing this + SpellCastResult result = SpellCastResult.SpellCastOk; + UnitFlags unitflag = (UnitFlags)pet.m_unitData.Flags._value; + if (!pet.GetCharmerGUID().IsEmpty()) + result = SpellCastResult.Charmed; + else if (unitflag.HasAnyFlag(UnitFlags.Stunned)) + result = SpellCastResult.Stunned; + else if (unitflag.HasAnyFlag(UnitFlags.Fleeing)) + result = SpellCastResult.Fleeing; + else if (unitflag.HasAnyFlag(UnitFlags.Confused)) + result = SpellCastResult.Confused; + + if (result != SpellCastResult.SpellCastOk) + return result; + + Unit target = GetExplTargetUnit(); + if (target == null) + return SpellCastResult.BadTargets; + + if (!pet.IsWithinLOSInMap(target)) + return SpellCastResult.LineOfSight; + + return SpellCastResult.SpellCastOk; + } + + void HandleDummy(uint effIndex) + { + GetCaster().ToPlayer().GetPet().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); + } + + void HandleScriptEffect(uint effIndex) + { + GetHitUnit().CastSpell(null, SpellIds.MastersCallTriggered, true); + } + + public override void Register() + { + OnCheckCast.Add(new(DoCheckCast)); + + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 34477 - Misdirection +class spell_hun_misdirection : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MisdirectionProc); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Default || GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Interrupt) + return; + + if (!GetTarget().HasAura(SpellIds.MisdirectionProc)) + GetTarget().GetThreatManager().UnregisterRedirectThreat(SpellIds.Misdirection); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.MisdirectionProc, aurEff); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 35079 - Misdirection (Proc) +class spell_hun_misdirection_proc : AuraScript +{ + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().GetThreatManager().UnregisterRedirectThreat(SpellIds.Misdirection); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 2643 - Multi-Shot +class spell_hun_multi_shot : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MultiShotFocus); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleOnHit() + { + // We need to check hunter's spec because it doesn't generate focus on other specs than Mm + if (GetCaster().ToPlayer().GetPrimarySpecialization() == ChrSpecialization.HunterMarksmanship) + GetCaster().CastSpell(GetCaster(), SpellIds.MultiShotFocus, true); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] // 459783 - Penetrating Shots +class spell_hun_penetrating_shots : AuraScript +{ + void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + AuraEffect amountHolder = GetEffect(1); + if (amountHolder != null) + { + float critChanceDone = GetUnitOwner().GetUnitCriticalChanceDone(WeaponAttackType.BaseAttack); + amount = (int)MathFunctions.CalculatePct(critChanceDone, amountHolder.GetAmount()); + } + } + + void UpdatePeriodic(AuraEffect aurEff) + { + AuraEffect bonus = GetEffect(0); + if (bonus != null) + bonus.RecalculateAmount(aurEff); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalcAmount, 0, AuraType.ModCritDamageBonus)); + OnEffectPeriodic.Add(new(UpdatePeriodic, 1, AuraType.PeriodicDummy)); + } +} + +[Script] // 55709 - Pet Heart of the Phoenix +class spell_hun_pet_heart_of_the_phoenix : SpellScript +{ + public override bool Load() + { + if (!GetCaster().IsPet()) + return false; + return true; + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PetHeartOfThePhoenixTriggered, SpellIds.PetHeartOfThePhoenixDebuff); + } + + void HandleScript(uint effIndex) + { + Unit caster = GetCaster(); + Unit owner = caster.GetOwner(); + if (owner != null) + { + if (!caster.HasAura(SpellIds.PetHeartOfThePhoenixDebuff)) + { + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.AddSpellMod(SpellValueMod.BasePoint0, 100); + owner.CastSpell(caster, SpellIds.PetHeartOfThePhoenixTriggered, args); + caster.CastSpell(caster, SpellIds.PetHeartOfThePhoenixDebuff, true); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 781 - Disengage +class spell_hun_posthaste : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PosthasteTalent, SpellIds.PosthasteIncreaseSpeed); + } + + void HandleAfterCast() + { + if (GetCaster().HasAura(SpellIds.PosthasteTalent)) + { + GetCaster().RemoveMovementImpairingAuras(true); + GetCaster().CastSpell(GetCaster(), SpellIds.PosthasteIncreaseSpeed, GetSpell()); + } + } + + public override void Register() + { + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 260240 - Precise Shots +class spell_hun_precise_shots : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PreciseShots); + } + + void HandleProc(ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.PreciseShots, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = eventInfo.GetProcSpell() + }); + } + + public override void Register() + { + OnProc.Add(new(HandleProc)); + } +} + +[Script] // 257044 - Rapid Fire +class spell_hun_rapid_fire : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RapidFireDamage); + } + + void HandlePeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.RapidFireDamage, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodic, 1, AuraType.PeriodicDummy)); + } +} + +[Script] // 257045 - Rapid Fire Damage +class spell_hun_rapid_fire_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RapidFireEnergize); + } + + void HandleHit(uint effIndex) + { + GetCaster().CastSpell(null, SpellIds.RapidFireEnergize, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 385539 - Rejuvenating Wind +class spell_hun_rejuvenating_wind : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RejuvenatingWindHeal) + && Global.SpellMgr.GetSpellInfo(SpellIds.RejuvenatingWindHeal, Difficulty.None).GetMaxTicks() > 0; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procEvent) + { + PreventDefaultAction(); + + Unit caster = GetTarget(); + + uint ticks = Global.SpellMgr.GetSpellInfo(SpellIds.RejuvenatingWindHeal, Difficulty.None).GetMaxTicks(); + int heal = (int)(MathFunctions.CalculatePct(caster.GetMaxHealth(), aurEff.GetAmount()) / ticks); + + caster.CastSpell(caster, SpellIds.RejuvenatingWindHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, heal) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 53480 - Roar of Sacrifice +class spell_hun_roar_of_sacrifice : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RoarOfSacrificeTriggered); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || ((int)damageInfo.GetSchoolMask() & aurEff.GetMiscValue()) == 0) + return false; + + if (GetCaster() == null) + return false; + + return true; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), aurEff.GetAmount())); + eventInfo.GetActor().CastSpell(GetCaster(), SpellIds.RoarOfSacrificeTriggered, args); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 1, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 37506 - Scatter Shot +class spell_hun_scatter_shot : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleDummy(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + // break Auto Shot and autohit + caster.InterruptSpell(CurrentSpellTypes.AutoRepeat); + caster.AttackStop(); + caster.SendAttackSwingCancelAttack(); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 459455 - Scout's Instincts (attached to 186257 - Aspect of the Cheetah) +class spell_hun_scouts_instincts : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ScoutsInstincts) + && ValidateSpellEffect((spellInfo.Id, 1)) + && spellInfo.GetEffect(1).IsAura(AuraType.ModMinimumSpeed); + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.ScoutsInstincts); + } + + static void HandleMinSpeed(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(HandleMinSpeed, 1, Targets.UnitCaster)); + } +} + +[Script] // 459533 - Scrappy +class spell_hun_scrappy : AuraScript +{ + static uint[] AffectedSpellIds = [SpellIds.BindingShot, SpellIds.Intimidation, SpellIds.IntimidationMarksmanship]; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(AffectedSpellIds); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + foreach (uint spellId in AffectedSpellIds) + GetTarget().GetSpellHistory().ModifyCooldown(spellId, -TimeSpan.FromSeconds(aurEff.GetAmount())); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 473520 - Shrapnel Shot +class spell_hun_shrapnel_shot : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LockAndLoad); + } + + void HandleProc(ProcEventInfo eventInfo) + { + if (!RandomHelper.randChance(GetEffect(0).GetAmount())) + return; + + GetCaster().CastSpell(GetCaster(), SpellIds.LockAndLoad, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); + } + + public override void Register() + { + OnProc.Add(new(HandleProc)); + } +} + +[Script] // 56641 - Steady Shot +class spell_hun_steady_shot : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SteadyShotFocus, SpellIds.AimedShot, SpellIds.MarksmanshipHunterAura); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleOnHit() + { + GetCaster().CastSpell(GetCaster(), SpellIds.SteadyShotFocus, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + + if (GetCaster().HasAura(SpellIds.MarksmanshipHunterAura)) + GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.AimedShot, TimeSpan.FromSeconds(-GetEffectInfo(1).CalcValue())); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] // 260367 - Streamline (attached to 257044 - Rapid Fire) +class spell_hun_streamline : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StreamlineTalent, SpellIds.StreamlineBuff); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.StreamlineTalent); + } + + void HandleAfterCast() + { + GetCaster().CastSpell(GetCaster(), SpellIds.StreamlineBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 391559 - Surging Shots +class spell_hun_surging_shots : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RapidFire); + } + + void HandleProc(ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ResetCooldown(SpellIds.RapidFire, true); + } + + public override void Register() + { + OnProc.Add(new(HandleProc)); + } +} + +[Script] // 1515 - Tame Beast +class spell_hun_tame_beast : SpellScript +{ + static uint[] CallPetSpellIds = + [ + 883, + 83242, + 83243, + 83244, + 83245, + ]; + + SpellCastResult CheckCast() + { + Player caster = GetCaster().ToPlayer(); + if (caster == null) + return SpellCastResult.DontReport; + + if (GetExplTargetUnit() == null) + return SpellCastResult.BadImplicitTargets; + + Creature target = GetExplTargetUnit().ToCreature(); + if (target != null) + { + if (target.GetLevelForTarget(caster) > caster.GetLevel()) + return SpellCastResult.Highlevel; + + // use SmsgPetTameFailure? + if (!target.GetCreatureTemplate().IsTameable(caster.CanTameExoticPets(), target.GetCreatureDifficulty())) + return SpellCastResult.BadTargets; + + PetStable petStable = caster.GetPetStable(); + if (petStable != null) + { + if (petStable.CurrentPetIndex.HasValue) + return SpellCastResult.AlreadyHaveSummon; + + var freeSlotIndex = petStable.ActivePets.ToList().FindIndex(petInfo => petInfo == null); + if (freeSlotIndex == -1) + { + caster.SendTameFailure(PetTameResult.TooMany); + return SpellCastResult.DontReport; + } + + // Check for known Call Pet X spells + if (!caster.HasSpell(CallPetSpellIds[freeSlotIndex])) + { + caster.SendTameFailure(PetTameResult.TooMany); + return SpellCastResult.DontReport; + } + } + + if (!caster.GetCharmedGUID().IsEmpty()) + return SpellCastResult.AlreadyHaveCharm; + + if (!target.GetOwnerGUID().IsEmpty()) + { + caster.SendTameFailure(PetTameResult.CreatureAlreadyOwned); + return SpellCastResult.DontReport; + } + } + + else + return SpellCastResult.BadImplicitTargets; + + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + } +} + +// 187700 - Tar Trap +[Script] // 4436 - AreatriggerId +class areatrigger_hun_tar_trap(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnCreate(Spell creatingSpell) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (caster.HasAura(SpellIds.EntrapmentTalent)) + caster.CastSpell(at.GetPosition(), SpellIds.EntrapmentRoot, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, SpellIds.TarTrapSlow, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + } + + public override void OnUnitExit(Unit unit) + { + unit.RemoveAurasDueToSpell(SpellIds.TarTrapSlow, at.GetCasterGUID()); + } +} + +// 187699 - Tar Trap +[Script] // 4435 - AreatriggerId +class areatrigger_hun_tar_trap_activate(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnInitialize() + { + Unit caster = at.GetCaster(); + if (caster != null) + foreach (AreaTrigger other in caster.GetAreaTriggers(SpellIds.TarTrap)) + other.SetDuration(0); + } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (caster.IsValidAttackTarget(unit)) + { + caster.CastSpell(at.GetPosition(), SpellIds.TarTrapAreatrigger, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + at.Remove(); + } + } + } +} + +[Script] // 67151 - Item - Hunter T9 4P Bonus (Steady Shot) +class spell_hun_t9_4p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.T9_4PGreatness); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetActor().IsPlayer() && eventInfo.GetActor().ToPlayer().GetPet() != null) + return true; + return false; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + + caster.CastSpell(caster.ToPlayer().GetPet(), SpellIds.T9_4PGreatness, aurEff); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 394366 - Find The Mark +class spell_hun_t29_2p_marksmanship_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.T29_2PMarksmanshipDamage, 0)) + && Global.SpellMgr.GetSpellInfo(SpellIds.T29_2PMarksmanshipDamage, Difficulty.None).GetMaxTicks() != 0; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + uint ticks = Global.SpellMgr.GetSpellInfo(SpellIds.T29_2PMarksmanshipDamage, Difficulty.None).GetMaxTicks(); + uint damage = MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetOriginalDamage(), aurEff.GetAmount()) / ticks; + + caster.CastSpell(eventInfo.GetActionTarget(), SpellIds.T29_2PMarksmanshipDamage, new CastSpellExtraArgs(aurEff) + .SetTriggeringSpell(eventInfo.GetProcSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, (int)damage)); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // Called by 136 - Mend Pet +class spell_hun_wilderness_medicine : AuraScript +{ + int _dispelChance = 0; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.WildernessMedicineTalent, SpellIds.WildernessMedicineDispel); + } + + public override bool Load() + { + Unit caster = GetCaster(); + if (caster == null) + return false; + + AuraEffect wildernessMedicine = GetCaster().GetAuraEffect(SpellIds.WildernessMedicineTalent, 1); + if (wildernessMedicine == null) + return false; + + _dispelChance = wildernessMedicine.GetAmount(); + return true; + } + + void OnPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + { + if (RandomHelper.randChance(_dispelChance)) + { + caster.CastSpell(GetTarget(), SpellIds.WildernessMedicineDispel, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.ObsModHealth)); + } +} \ No newline at end of file diff --git a/Source/Scripts/Spells/Item.cs b/Source/Scripts/Spells/Item.cs index bebbf03fc..33fab1268 100644 --- a/Source/Scripts/Spells/Item.cs +++ b/Source/Scripts/Spells/Item.cs @@ -1,9 +1,29 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +/* + * This file is part of the TrinityCore Project. See Authors file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the Gnu General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but Without + * Any Warranty; without even the implied warranty of Merchantability or + * Fitness For A Particular Purpose. See the Gnu General Public License for + * more details. + * + * You should have received a copy of the Gnu General Public License along + * with this program. If not, see . + */ + +/* + * Scripts for spells with SpellfamilyGeneric spells used by items. + * Ordered alphabetically using scriptname. + * Scriptnames of files in this file should be prefixed with "spell_item_". + */ + using Framework.Constants; using Framework.Dynamic; -using Game.BattleGrounds; using Game.DataStorage; using Game.Entities; using Game.Loots; @@ -13,4140 +33,4292 @@ using Game.Spells; using System; using System.Collections.Generic; using System.Linq; -using static Global; -namespace Scripts.Spells.Azerite +namespace Scripts.Spells.Items; + +struct SpellIds { - // 23074 Arcanite Dragonling - [Script("spell_item_arcanite_dragonling", SpellArcaniteDragonling)] - // 23133 Gnomish Battle Chicken - [Script("spell_item_gnomish_battle_chicken", SpellBattleChicken)] - // 23076 Mechanical Dragonling - [Script("spell_item_mechanical_dragonling", SpellMechanicalDragonling)] - // 23075 Mithril Mechanical Dragonling - [Script("spell_item_mithril_mechanical_dragonling", SpellMithrilMechanicalDragonling)] - class spell_item_trigger_spell_SpellScript : SpellScript + // GenericData + public const uint ArcaniteDragonling = 19804; + public const uint BattleChicken = 13166; + public const uint MechanicalDragonling = 4073; + public const uint MithrilMechanicalDragonling = 12749; + + // AegisOfPreservation + public const uint AegisHeal = 23781; + + // ZezzaksShard + public const uint EyeOfGrillok = 38495; + + // LowerCityPrayerbook + public const uint BlessingOfLowerCityDruid = 37878; + public const uint BlessingOfLowerCityPaladin = 37879; + public const uint BlessingOfLowerCityPriest = 37880; + public const uint BlessingOfLowerCityShaman = 37881; + + // AlchemistStone + public const uint AlchemistStoneExtraHeal = 21399; + public const uint AlchemistStoneExtraMana = 21400; + + // AngerCapacitor + public const uint MoteOfAnger = 71432; + public const uint ManifestAngerMainHand = 71433; + public const uint ManifestAngerOffHand = 71434; + + // AuraOfMadness + public const uint Sociopath = 39511; // Sociopath: +35 strength(Paladin; Rogue; Druid; Warrior) + public const uint Delusional = 40997; // Delusional: +70 attack power(Rogue; Hunter; Paladin; Warrior; Druid) + public const uint Kleptomania = 40998; // Kleptomania: +35 agility(Warrior; Rogue; Paladin; Hunter; Druid) + public const uint Megalomania = 40999; // Megalomania: +41 damage / healing(Druid; Shaman; Priest; Warlock; Mage; Paladin) + public const uint Paranoia = 41002; // Paranoia: +35 spell / melee / ranged crit strike rating(All classes) + public const uint Manic = 41005; // Manic: +35 haste(spell; melee and ranged) (All classes) + public const uint Narcissism = 41009; // Narcissism: +35 intellect(Druid; Shaman; Priest; Warlock; Mage; Paladin; Hunter) + public const uint MartyrComplex = 41011; // Martyr Complex: +35 stamina(All classes) + public const uint Dementia = 41404; // Dementia: Every 5 seconds either gives you +5/-5% damage/healing. (Druid; Shaman; Priest; Warlock; Mage; Paladin) + public const uint DementiaPos = 41406; + public const uint DementiaNeg = 41409; + + // BrittleArmor + public const uint BrittleArmor = 24575; + + // BlessingOfAncientKings + public const uint ProtectionOfAncientKings = 64413; + + // DeadlyPrecision + public const uint DeadlyPrecision = 71564; + + // DeathbringersWill + public const uint StrengthOfTheTaunka = 71484; // +600 Strength + public const uint AgilityOfTheVrykul = 71485; // +600 Agility + public const uint PowerOfTheTaunka = 71486; // +1200 Attack Power + public const uint AimOfTheIronDwarves = 71491; // +600 Critical + public const uint SpeedOfTheVrykul = 71492; // +600 Haste + + public const uint AgilityOfTheVrykulHero = 71556; // +700 Agility + public const uint PowerOfTheTaunkaHero = 71558; // +1400 Attack Power + public const uint AimOfTheIronDwarvesHero = 71559; // +700 Critical + public const uint SpeedOfTheVrykulHero = 71560; // +700 Haste + public const uint StrengthOfTheTaunkaHero = 71561; // +700 Strength + + // GoblinBombDispenser + public const uint SummonGoblinBomb = 13258; + public const uint MalfunctionExplosion = 13261; + + // GoblinWeatherMachine + public const uint PersonalizedWeather1 = 46740; + public const uint PersonalizedWeather2 = 46739; + public const uint PersonalizedWeather3 = 46738; + public const uint PersonalizedWeather4 = 46736; + + // Defibrillate + public const uint GoblinJumperCablesFail = 8338; + public const uint GoblinJumperCablesXlFail = 23055; + + // DesperateDefense + public const uint DesperateRage = 33898; + + // DeviateFishSpells + public const uint Sleepy = 8064; + public const uint Invigorate = 8065; + public const uint Shrink = 8066; + public const uint PartyTime = 8067; + public const uint HealthySpirit = 8068; + public const uint Rejuvenation = 8070; + + // DiscerningEyeBeastMisc + public const uint DiscerningEyeBeast = 59914; + + // FateRuneOfUnsurpassedVigor + public const uint UnsurpassedVigor = 25733; + + // FlaskOfTheNorthSpells + public const uint FlaskOfTheNorthSp = 67016; + public const uint FlaskOfTheNorthAp = 67017; + public const uint FlaskOfTheNorthStr = 67018; + + // FrozenShadoweave + public const uint Shadowmend = 39373; + + // GnomishDeathRay + public const uint GnomishDeathRaySelf = 13493; + public const uint GnomishDeathRayTarget = 13279; + + // HarmPreventionBelt + public const uint ForcefieldCollapse = 13235; + + // Heartpierce + public const uint InvigorationMana = 71881; + public const uint InvigorationEnergy = 71882; + public const uint InvigorationRage = 71883; + public const uint InvigorationRp = 71884; + + public const uint InvigorationRpHero = 71885; + public const uint InvigorationRageHero = 71886; + public const uint InvigorationEnergyHero = 71887; + public const uint InvigorationManaHero = 71888; + + // HourglassSand + public const uint BroodAfflictionBronze = 23170; + + // MakeAWish + public const uint MrPinchysBlessing = 33053; + public const uint SummonMightyMrPinchy = 33057; + public const uint SummonFuriousMrPinchy = 33059; + public const uint TinyMagicalCrawdad = 33062; + public const uint MrPinchysGift = 33064; + + // MarkOfConquest + public const uint MarkOfConquestEnergize = 39599; + + // MercurialShield + public const uint MercurialShield = 26464; + + // MingoFortune + public const uint CreateFortune1 = 40804; + public const uint CreateFortune2 = 40805; + public const uint CreateFortune3 = 40806; + public const uint CreateFortune4 = 40807; + public const uint CreateFortune5 = 40808; + public const uint CreateFortune6 = 40809; + public const uint CreateFortune7 = 40908; + public const uint CreateFortune8 = 40910; + public const uint CreateFortune9 = 40911; + public const uint CreateFortune10 = 40912; + public const uint CreateFortune11 = 40913; + public const uint CreateFortune12 = 40914; + public const uint CreateFortune13 = 40915; + public const uint CreateFortune14 = 40916; + public const uint CreateFortune15 = 40918; + public const uint CreateFortune16 = 40919; + public const uint CreateFortune17 = 40920; + public const uint CreateFortune18 = 40921; + public const uint CreateFortune19 = 40922; + public const uint CreateFortune20 = 40923; + + // NecroticTouch + public const uint ItemNecroticTouchProc = 71879; + + // NetOMaticSpells + public const uint NetOMaticTRIGGERED1 = 16566; + public const uint NetOMaticTRIGGERED2 = 13119; + public const uint NetOMaticTRIGGERED3 = 13099; + + // NoggenfoggerElixirSpells + public const uint NoggenfoggerElixirTRIGGERED1 = 16595; + public const uint NoggenfoggerElixirTRIGGERED2 = 16593; + public const uint NoggenfoggerElixirTRIGGERED3 = 16591; + + // PersistentShieldMisc + public const uint PersistentShieldTriggered = 26470; + + // PetHealing + public const uint HealthLink = 37382; + + // PowerCircle + public const uint LimitlessPower = 45044; + + // SavoryDeviateDelight + public const uint FlipOutMale = 8219; + public const uint FlipOutFemale = 8220; + public const uint YaaarrrrMale = 8221; + public const uint YaaarrrrFemale = 8222; + + // ScrollOfRecall + public const uint ScrollOfRecallI = 48129; + public const uint ScrollOfRecallIi = 60320; + public const uint ScrollOfRecallIii = 60321; + public const uint Lost = 60444; + public const uint ScrollOfRecallFailAlliance1 = 60323; + public const uint ScrollOfRecallFailHorde1 = 60328; + + // TransporterSpells + public const uint EvilTwin = 23445; + public const uint TransporterMalfunctionFire = 23449; + public const uint TransporterMalfunctionSmaller = 36893; + public const uint TransporterMalfunctionBigger = 36895; + public const uint TransporterMalfunctionChicken = 36940; + public const uint TransformHorde = 36897; + public const uint TransformAlliance = 36899; + public const uint SoulSplitEvil = 36900; + public const uint SoulSplitGood = 36901; + + // ShadowsFate + public const uint SoulFeast = 71203; + + // Shadowmourne + public const uint ShadowmourneChaosBaneDamage = 71904; + public const uint ShadowmourneSoulFragment = 71905; + public const uint ShadowmourneVisualLow = 72521; + public const uint ShadowmourneVisualHigh = 72523; + public const uint ShadowmourneChaosBaneBuff = 73422; + + // SixDemonBagSpells + public const uint Frostbolt = 11538; + public const uint Polymorph = 14621; + public const uint SummonFelhoundMinion = 14642; + public const uint Fireball = 15662; + public const uint ChainLightning = 21179; + public const uint EnvelopingWinds = 25189; + + // SwiftHandJusticeMisc + public const uint SwiftHandOfJusticeHeal = 59913; + + // UnderbellyElixirSpells + public const uint UnderbellyElixirTriggered1 = 59645; + public const uint UnderbellyElixirTriggered2 = 59831; + public const uint UnderbellyElixirTriggered3 = 59843; + + // WormholeGeneratorPandariaSpell + public const uint WormholePandariaIsleOfReckoning = 126756; + public const uint WormholePandariaKunlaiUnderwater = 126757; + public const uint WormholePandariaSraVess = 126758; + public const uint WormholePandariaRikkitunVillage = 126759; + public const uint WormholePandariaZanvessTree = 126760; + public const uint WormholePandariaAnglersWharf = 126761; + public const uint WormholePandariaCraneStatue = 126762; + public const uint WormholePandariaEmperorsOmen = 126763; + public const uint WormholePandariaWhitepetalLake = 126764; + + // AirRifleSpells + public const uint AirRifleHoldVisual = 65582; + public const uint AirRifleShoot = 67532; + public const uint AirRifleShootSelf = 65577; + + // VanquishedClutchesSpells + public const uint Crusher = 64982; + public const uint Constrictor = 64983; + public const uint Corruptor = 64984; + + // MagicEater + public const uint WildMagic = 58891; + public const uint WellFed1 = 57288; + public const uint WellFed2 = 57139; + public const uint WellFed3 = 57111; + public const uint WellFed4 = 57286; + public const uint WellFed5 = 57291; + + // PurifyHelboarMeat + public const uint SummonPurifiedHelboarMeat = 29277; + public const uint SummonToxicHelboarMeat = 29278; + + // NighInvulnerability + public const uint NighInvulnerability = 30456; + public const uint CompleteVulnerability = 30457; + + // Poultryzer + public const uint PoultryizerSuccess = 30501; + public const uint PoultryizerBackfire = 30504; + + // SocretharsStone + public const uint SocretharToSeat = 35743; + public const uint SocretharFromSeat = 35744; + + // DemonBroiledSurprise + public const uint CreateDemonBroiledSurprise = 43753; + + // CompleteRaptorCapture + public const uint RaptorCaptureCredit = 42337; + + // ImpaleLeviroth + public const uint LevirothSelfImpale = 49882; + + // LifegivingGem + public const uint GiftOfLife1 = 23782; + public const uint GiftOfLife2 = 23783; + + // NitroBoosts + public const uint NitroBoostsSuccess = 54861; + public const uint NitroBoostsBackfire = 54621; + public const uint NitroBoostsParachute = 54649; + + // RocketBoots + public const uint RocketBootsProc = 30452; + + // PygmyOil + public const uint PygmyOilPygmyAura = 53806; + public const uint PygmyOilSmallerAura = 53805; + + // ChickenCover + public const uint ChickenNet = 51959; + public const uint CaptureChickenEscape = 51037; + + // GreatmothersSoulcather + public const uint ForceCastSummonGnomeSoul = 46486; + + // ShardOfTheScale + public const uint PurifiedCauterizingHeal = 69733; + public const uint PurifiedSearingFlames = 69729; + + public const uint ShinyCauterizingHeal = 69734; + public const uint ShinySearingFlames = 69730; + + // SoulPreserver + public const uint SoulPreserverDruid = 60512; + public const uint SoulPreserverPaladin = 60513; + public const uint SoulPreserverPriest = 60514; + public const uint SoulPreserverShaman = 60515; + + // ExaltedSunwellNeck + public const uint LightsWrath = 45479; // Light's Wrath if Exalted by Aldor + public const uint ArcaneBolt = 45429; // Arcane Bolt if Exalted by Scryers + + public const uint LightsStrength = 45480; // Light's Strength if Exalted by Aldor + public const uint ArcaneStrike = 45428; // Arcane Strike if Exalted by Scryers + + public const uint LightsWard = 45432; // Light's Ward if Exalted by Aldor + public const uint ArcaneInsight = 45431; // Arcane Insight if Exalted by Scryers + + public const uint LightsSalvation = 45478; // Light's Salvation if Exalted by Aldor + public const uint ArcaneSurge = 45430; // Arcane Surge if Exalted by Scryers + + // DeathChoiceSpells + public const uint DeathChoiceNormalAura = 67702; + public const uint DeathChoiceNormalAgility = 67703; + public const uint DeathChoiceNormalStrength = 67708; + public const uint DeathChoiceHeroicAura = 67771; + public const uint DeathChoiceHeroicAgility = 67772; + public const uint DeathChoiceHeroicStrength = 67773; + + // TrinketStackSpells + public const uint LightningCapacitorAura = 37657; // Lightning Capacitor + public const uint LightningCapacitorStack = 37658; + public const uint LightningCapacitorTrigger = 37661; + public const uint ThunderCapacitorAura = 54841; // Thunder Capacitor + public const uint ThunderCapacitorStack = 54842; + public const uint ThunderCapacitorTrigger = 54843; + public const uint TOC25_CasterTrinketNormalAura = 67712; // Item - Coliseum 25 Normal Caster Trinket + public const uint TOC25CasterTrinketNormalStack = 67713; + public const uint TOC25CasterTrinketNormalTrigger = 67714; + public const uint TOC25_CasterTrinketHeroicAura = 67758; // Item - Coliseum 25 Heroic Caster Trinket + public const uint TOC25CasterTrinketHeroicStack = 67759; + public const uint TOC25CasterTrinketHeroicTrigger = 67760; + + // DarkmoonCardSpells + public const uint DarkmoonCardStrength = 60229; + public const uint DarkmoonCardAgility = 60233; + public const uint DarkmoonCardIntellect = 60234; + public const uint DarkmoonCardVersatility = 60235; + + // ManaDrainSpells + public const uint ManaDrainEnergize = 29471; + public const uint ManaDrainLeech = 27526; + + // TauntFlag + public const uint TauntFlag = 51657; + + // MirrensDrinkingHat + public const uint LochModanLager = 29827; + public const uint StouthammerLite = 29828; + public const uint AeriePeakPaleAle = 29829; + + // MindControlCap + public const uint GnomishMindControlCap = 13181; + public const uint Dullard = 67809; + + // UniversalRemote + public const uint ControlMachine = 8345; + public const uint MobilityMalfunction = 8346; + public const uint TargetLock = 8347; + + // ZandalarianCharms + public const uint UnstablePowerAuraStack = 24659; + public const uint RestlessStrengthAuraStack = 24662; + + // AuraProcRemoveSpells + public const uint TalismanOfAscendance = 28200; + public const uint JomGabbar = 29602; + public const uint BattleTrance = 45040; + public const uint WorldQuellerFocus = 90900; + public const uint BrutalKinship1 = 144671; + public const uint BrutalKinship2 = 145738; + + // Eggnog + public const uint EggNogReindeer = 21936; + public const uint EggNogSnowman = 21980; + + // SephuzsSecret + public const uint SephuzsSecretCooldown = 226262; + + // AmalgamsSeventhSpine + public const uint FragileEchoesMonk = 225281; + public const uint FragileEchoesShaman = 225292; + public const uint FragileEchoesPriestDiscipline = 225294; + public const uint FragileEchoesPaladin = 225297; + public const uint FragileEchoesDruid = 225298; + public const uint FragileEchoesPriestHoly = 225366; + public const uint FragileEchoesEvoker = 429020; + public const uint FragileEchoEnergize = 215270; + + // HighfathersMachination + public const uint HighfathersTimekeepingHeal = 253288; + + // SeepingScourgewing + public const uint ShadowStrikeAoeCheck = 255861; + public const uint IsolatedStrike = 255609; + + // ShiverVenomSpell + public const uint ShiverVenom = 301624; + public const uint ShiveringBolt = 303559; + public const uint VenomousLance = 303562; + + // MettleSpell + public const uint MettleCooldown = 410532; +} + +struct MiscConst +{ + // AuraOfMadness + public const uint SayMadness = 21954; + + //Roll Dice + public const uint TextDecahedralDwarvenDice = 26147; + + // DireBrew + public const uint ModelClassClothMale = 25229; + public const uint ModelClassClothFemale = 25233; + public const uint ModelClassLeatherMale = 25230; + public const uint ModelClassLeatherFemale = 25234; + public const uint ModelClassMailMale = 25231; + public const uint ModelClassMailFemale = 25235; + public const uint ModelClassPlateMale = 25232; + public const uint ModelClassPlateFemale = 25236; + + // Feast + public const uint TextGreatFeast = 31843; + public const uint TextFishFeast = 31844; + public const uint TextGiganticFeast = 31846; + public const uint TextSmallFeast = 31845; + public const uint TextBountifulFeast = 35153; + + // ShadowsFate + public const uint NpcSindragosa = 36853; + + // Roll 'dem Bones + public const uint TextWornTrollDice = 26152; + + // GiftOfTheHarvester + public const uint NpcGhoul = 28845; + public const uint MaxGhouls = 5; + + // Sinkholes + public const uint NpcSouthSinkhole = 25664; + public const uint NpcNortheastSinkhole = 25665; + public const uint NpcNorthwestSinkhole = 25666; + + // AshbringerSounds + public const uint SoundAshbringer1 = 8906; // "I was pure once" + public const uint SoundAshbringer2 = 8907; // "Fought for righteousness" + public const uint SoundAshbringer3 = 8908; // "I was once called Ashbringer" + public const uint SoundAshbringer4 = 8920; // "Betrayed by my order" + public const uint SoundAshbringer5 = 8921; // "Destroyed by Kel'Thuzad" + public const uint SoundAshbringer6 = 8922; // "Made to serve" + public const uint SoundAshbringer7 = 8923; // "My son watched me die" + public const uint SoundAshbringer8 = 8924; // "Crusades fed his rage" + public const uint SoundAshbringer9 = 8925; // "Truth is unknown to him" + public const uint SoundAshbringer10 = 8926; // "Scarlet Crusade is pure no longer" + public const uint SoundAshbringer11 = 8927; // "Balnazzar's crusade corrupted my son" + public const uint SoundAshbringer12 = 8928; // "Kill them all!" + + // DemonBroiledSurprise + public const uint QuestSuperHotStew = 11379; + public const uint NpcAbyssalFlamebringer = 19973; + + + // ImpaleLeviroth + public const uint NpcLeviroth = 26452; + + // ChickenCover + public const uint QuestChickenParty = 12702; + public const uint QuestFlownTheCoop = 12532; + + // ExaltedSunwellNeck + public const uint FactionAldor = 932; + public const uint FactionScryers = 934; + + // TauntFlag + public const uint EmotePlantsFlag = 28008; + + + // MindControlCap + public const uint RollChanceDullard = 32; + public const uint RollChanceNoBackfire = 95; +} + +[Script("spell_item_arcanite_dragonling", SpellIds.ArcaniteDragonling)] // 23074 Arcanite Dragonling +[Script("spell_item_gnomish_battle_chicken", SpellIds.BattleChicken)] // 23133 Gnomish Battle Chicken +[Script("spell_item_mechanical_dragonling", SpellIds.MechanicalDragonling)] // 23076 Mechanical Dragonling +[Script("spell_item_mithril_mechanical_dragonling", SpellIds.MithrilMechanicalDragonling)] // 23075 Mithril Mechanical Dragonling +class spell_item_trigger_spell(uint triggeredSpellId) : SpellScript() +{ + public override bool Validate(SpellInfo spellInfo) { - const uint SpellArcaniteDragonling = 19804; - const uint SpellBattleChicken = 13166; - const uint SpellMechanicalDragonling = 4073; - const uint SpellMithrilMechanicalDragonling = 12749; - - uint _triggeredSpellId; - - public spell_item_trigger_spell_SpellScript(uint triggeredSpellId) - { - _triggeredSpellId = triggeredSpellId; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_triggeredSpellId); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Item item = GetCastItem(); - if (item != null) - caster.CastSpell(caster, _triggeredSpellId, item); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + return ValidateSpellInfo(triggeredSpellId); } - [Script] // 23780 - Aegis of Preservation - class spell_item_aegis_of_preservation : AuraScript + void HandleDummy(uint effIndex) { - const uint SpellAegisHeal = 23781; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellAegisHeal); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellAegisHeal, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 1, AuraType.ProcTriggerSpell)); - } + Unit caster = GetCaster(); Item item = GetCastItem(); + if (item != null) + caster.CastSpell(caster, triggeredSpellId, item); } - [Script] // 37877 - Blessing of Faith - class spell_item_blessing_of_faith : SpellScript + public override void Register() { - const uint SpellBlessingOfLowerCityDruid = 37878; - const uint SpellBlessingOfLowerCityPaladin = 37879; - const uint SpellBlessingOfLowerCityPriest = 37880; - const uint SpellBlessingOfLowerCityShaman = 37881; + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellBlessingOfLowerCityDruid, SpellBlessingOfLowerCityPaladin, SpellBlessingOfLowerCityPriest, SpellBlessingOfLowerCityShaman); - } - - void HandleDummy(uint effIndex) - { - Unit unitTarget = GetHitUnit(); - if (unitTarget != null) - { - uint spellId; - switch (unitTarget.GetClass()) - { - case Class.Druid: - spellId = SpellBlessingOfLowerCityDruid; - break; - case Class.Paladin: - spellId = SpellBlessingOfLowerCityPaladin; - break; - case Class.Priest: - spellId = SpellBlessingOfLowerCityPriest; - break; - case Class.Shaman: - spellId = SpellBlessingOfLowerCityShaman; - break; - default: - return; // ignore for non-healing classes - } - - Unit caster = GetCaster(); - caster.CastSpell(caster, spellId, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } +[Script] // 23780 - Aegis of Preservation +class spell_item_aegis_of_preservation : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AegisHeal); } - // Item - 13503: Alchemist's Stone - // Item - 35748: Guardian's Alchemist Stone - // Item - 35749: Sorcerer's Alchemist Stone - // Item - 35750: Redeemer's Alchemist Stone - // Item - 35751: AssasMath.Sin's Alchemist Stone - // Item - 44322: Mercurial Alchemist Stone - // Item - 44323: Indestructible Alchemist's Stone - // Item - 44324: Mighty Alchemist's Stone - - [Script] // 17619 - Alchemist Stone - class spell_item_alchemist_stone : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - const uint SpellAlchemistStoneExtraHeal = 21399; - const uint SpellAlchemistStoneExtraMana = 21400; + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.AegisHeal, aurEff); + } - public override bool Validate(SpellInfo spellInfo) + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.ProcTriggerSpell)); + } +} + + +[Script] // 38554 - Absorb Eye of Grillok (31463: Zezzak's Shard) +class spell_item_absorb_eye_of_grillok : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EyeOfGrillok); + } + + void PeriodicTick(AuraEffect aurEff) + { + PreventDefaultAction(); + + if (GetCaster() == null || GetTarget().GetTypeId() != TypeId.Unit) + return; + + GetCaster().CastSpell(GetCaster(), SpellIds.EyeOfGrillok, aurEff); + GetTarget().ToCreature().DespawnOrUnsummon(); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicTriggerSpell)); + } +} + +// 37877 - Blessing of Faith +class spell_item_blessing_of_faith : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlessingOfLowerCityDruid, SpellIds.BlessingOfLowerCityPaladin, SpellIds.BlessingOfLowerCityPriest, SpellIds.BlessingOfLowerCityShaman); + } + + void HandleDummy(uint effIndex) + { + Unit unitTarget = GetHitUnit(); + if (unitTarget != null) { - return ValidateSpellInfo(SpellAlchemistStoneExtraHeal, SpellAlchemistStoneExtraMana); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetDamageInfo().GetSpellInfo().SpellFamilyName == SpellFamilyNames.Potion; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - uint spellId = 0; - int amount = (int)(eventInfo.GetDamageInfo().GetDamage() * 0.4f); - - if (eventInfo.GetDamageInfo().GetSpellInfo().HasEffect(SpellEffectName.Heal)) - spellId = SpellAlchemistStoneExtraHeal; - else if (eventInfo.GetDamageInfo().GetSpellInfo().HasEffect(SpellEffectName.Energize)) - spellId = SpellAlchemistStoneExtraMana; - - if (spellId == 0) - return; - - Unit caster = eventInfo.GetActionTarget(); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(null, spellId, args); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - // Item - 50351: Tiny Abomination in a Jar - // 71406 - Anger Capacitor - - // Item - 50706: Tiny Abomination in a Jar (Heroic) - // 71545 - Anger Capacitor - [Script("spell_item_tiny_abomination_in_a_jar", 8)] - [Script("spell_item_tiny_abomination_in_a_jar_hero", 7)] - class spell_item_anger_capacitor_AuraScript : AuraScript - { - const uint SpellMoteOfAnger = 71432; - const uint SpellManifestAngerMainHand = 71433; - const uint SpellManifestAngerOffHand = 71434; - - uint _stacks; - - public spell_item_anger_capacitor_AuraScript(uint stacks) - { - _stacks = stacks; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellMoteOfAnger, SpellManifestAngerMainHand, SpellManifestAngerOffHand); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - caster.CastSpell(null, SpellMoteOfAnger, true); - Aura motes = caster.GetAura(SpellMoteOfAnger); - if (motes == null || motes.GetStackAmount() < _stacks) - return; - - caster.RemoveAurasDueToSpell(SpellMoteOfAnger); - uint spellId = SpellManifestAngerMainHand; - Player player = caster.ToPlayer(); - if (player != null) - if (player.GetWeaponForAttack(WeaponAttackType.OffAttack, true) != null && RandomHelper.randChance(50)) - spellId = SpellManifestAngerOffHand; - - caster.CastSpell(target, spellId, aurEff); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellMoteOfAnger); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 26400 - Arcane Shroud - class spell_item_arcane_shroud : AuraScript - { - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - int diff = (int)(GetUnitOwner().GetLevel() - 60); - if (diff > 0) - amount += 2 * diff; - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModThreat)); - } - } - - // Item - 31859: Darkmoon Card: Madness - [Script] // 39446 - Aura of Madness - class spell_item_aura_of_madness : AuraScript - { - const uint SpellSociopath = 39511; // Sociopath: +35 strength(Paladin, Rogue, Druid, Warrior) - const uint SpellDelusional = 40997; // Delusional: +70 attack power(Rogue, Hunter, Paladin, Warrior, Druid) - const uint SpellKleptomania = 40998; // Kleptomania: +35 agility(Warrior, Rogue, Paladin, Hunter, Druid) - const uint SpellMegalomania = 40999; // Megalomania: +41 damage / healing(Druid, Shaman, Priest, Warlock, Mage, Paladin) - const uint SpellParanoia = 41002; // Paranoia: +35 spell / melee / ranged crit strike rating(All classes) - const uint SpellManic = 41005; // Manic: +35 haste(spell, melee and ranged) (All classes) - const uint SpellNarcissism = 41009; // Narcissism: +35 intellect(Druid, Shaman, Priest, Warlock, Mage, Paladin, Hunter) - const uint SpellMartyrComplex = 41011; // Martyr Complex: +35 stamina(All classes) - const uint SpellDementia = 41404; // Dementia: Every 5 seconds either gives you +5/-5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin) - - const uint SayMadness = 21954; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellSociopath, SpellDelusional, SpellKleptomania, SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia) && CliDB.BroadcastTextStorage.ContainsKey(SayMadness); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - uint[][] triggeredSpells = + switch (unitTarget.GetClass()) { - //ClassNone - Array.Empty(), - //ClassWarrior - new uint[] { SpellSociopath, SpellDelusional, SpellKleptomania, SpellParanoia, SpellManic, SpellMartyrComplex }, - //ClassPaladin - new uint[] { SpellSociopath, SpellDelusional, SpellKleptomania, SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia }, - //ClassHunter - new uint[] { SpellDelusional, SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia }, - //ClassRogue - new uint[] { SpellSociopath, SpellDelusional, SpellKleptomania, SpellParanoia, SpellManic, SpellMartyrComplex }, - //ClassPriest - new uint[] { SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia }, - //ClassDeathKnight - new uint[] { SpellSociopath, SpellDelusional, SpellKleptomania, SpellParanoia, SpellManic, SpellMartyrComplex }, - //ClassShaman - new uint[] { SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia }, - //ClassMage - new uint[] { SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia }, - //ClassWarlock - new uint[] { SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia }, - //ClassUnk - Array.Empty(), - //ClassDruid - new uint[] { SpellSociopath, SpellDelusional, SpellKleptomania, SpellMegalomania, SpellParanoia, SpellManic, SpellNarcissism, SpellMartyrComplex, SpellDementia } - }; - - - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - uint spellId = triggeredSpells[(int)caster.GetClass()].SelectRandom(); - caster.CastSpell(caster, spellId, aurEff); - - if (RandomHelper.randChance(10)) - caster.Say(SayMadness); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 41404 - Dementia - class spell_item_dementia : AuraScript - { - const uint SpellDementiaPos = 41406; - const uint SpellDementiaNeg = 41409; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDementiaPos, SpellDementiaNeg); - } - - void HandlePeriodicDummy(AuraEffect aurEff) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), RandomHelper.RAND(SpellDementiaPos, SpellDementiaNeg), aurEff); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodicDummy, 0, AuraType.PeriodicDummy)); - } - } - - [Script] // 24590 - Brittle Armor - class spell_item_brittle_armor : SpellScript - { - const uint SpellBrittleArmor = 24575; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellBrittleArmor); - } - - void HandleScript(uint effIndex) - { - GetHitUnit().RemoveAuraFromStack(SpellBrittleArmor); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 64411 - Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings) - class spell_item_blessing_of_ancient_kings : AuraScript - { - const uint SpellProtectionOfAncientKings = 64413; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellProtectionOfAncientKings); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo == null || healInfo.GetHeal() == 0) - return; - - int absorb = (int)MathFunctions.CalculatePct(healInfo.GetHeal(), 15.0f); - AuraEffect protEff = eventInfo.GetProcTarget().GetAuraEffect(SpellProtectionOfAncientKings, 0, eventInfo.GetActor().GetGUID()); - if (protEff != null) - { - // The shield can grow to a maximum size of 20,000 damage absorbtion - protEff.SetAmount(Math.Min(protEff.GetAmount() + absorb, 20000)); - - // Refresh and return to prevent replacing the aura - protEff.GetBase().RefreshDuration(); + case Class.Druid: + spellId = SpellIds.BlessingOfLowerCityDruid; + break; + case Class.Paladin: + spellId = SpellIds.BlessingOfLowerCityPaladin; + break; + case Class.Priest: + spellId = SpellIds.BlessingOfLowerCityPriest; + break; + case Class.Shaman: + spellId = SpellIds.BlessingOfLowerCityShaman; + break; + default: + return; // ignore for non-healing classes } - else - { - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, absorb); - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellProtectionOfAncientKings, args); - } - } - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 64415 Val'anyr Hammer of Ancient Kings - Equip Effect - class spell_item_valanyr_hammer_of_ancient_kings : AuraScript - { - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetHealInfo() != null && eventInfo.GetHealInfo().GetEffectiveHeal() > 0; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } - } - - [Script] // 71564 - Deadly Precision - class spell_item_deadly_precision : AuraScript - { - void HandleStackDrop(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().RemoveAuraFromStack(GetId(), GetTarget().GetGUID()); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleStackDrop, 0, AuraType.ModRating)); - } - } - - [Script] // 71563 - Deadly Precision Dummy - class spell_item_deadly_precision_dummy : SpellScript - { - const uint SpellDeadlyPrecision = 71564; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDeadlyPrecision); - } - - void HandleDummy(uint effIndex) - { - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellDeadlyPrecision, GetCastDifficulty()); - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.AuraStack, (int)spellInfo.StackAmount); - GetCaster().CastSpell(GetCaster(), spellInfo.Id, args); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.ApplyAura)); - } - } - - // Item - 50362: Deathbringer's Will - // 71519 - Item - Icecrown 25 Normal Melee Trinket - - // Item - 50363: Deathbringer's Will - // 71562 - Item - Icecrown 25 Heroic Melee Trinket - [Script("spell_item_deathbringers_will_normal", SpellStrengthOfTheTaunka, SpellAgilityOfTheVrykul, SpellPowerOfTheTaunka, SpellAimOfTheIronDwarves, SpellSpeedOfTheVrykul)] - [Script("spell_item_deathbringers_will_heroic", SpellStrengthOfTheTaunkaHero, SpellAgilityOfTheVrykulHero, SpellPowerOfTheTaunkaHero, SpellAimOfTheIronDwarvesHero, SpellSpeedOfTheVrykulHero)] - class spell_item_deathbringers_will_AuraScript : AuraScript - { - const uint SpellStrengthOfTheTaunka = 71484; // +600 Strength - const uint SpellAgilityOfTheVrykul = 71485; // +600 Agility - const uint SpellPowerOfTheTaunka = 71486; // +1200 Attack Power - const uint SpellAimOfTheIronDwarves = 71491; // +600 Critical - const uint SpellSpeedOfTheVrykul = 71492; // +600 Haste - - const uint SpellAgilityOfTheVrykulHero = 71556; // +700 Agility - const uint SpellPowerOfTheTaunkaHero = 71558; // +1400 Attack Power - const uint SpellAimOfTheIronDwarvesHero = 71559; // +700 Critical - const uint SpellSpeedOfTheVrykulHero = 71560; // +700 Haste - const uint SpellStrengthOfTheTaunkaHero = 71561; // +700 Strength - - uint _strength; - uint _agility; - uint _attackPower; - uint _critical; - uint _haste; - - public spell_item_deathbringers_will_AuraScript(uint strength, uint agility, uint attackPower, uint critical, uint haste) - { - _strength = strength; - _agility = agility; - _attackPower = attackPower; - _critical = critical; - _haste = haste; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_strength, _agility, _attackPower, _critical, _haste); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - uint[][] triggeredSpells = - { - //ClassNone - Array.Empty(), - //ClassWarrior - new uint[] { _strength, _critical, _haste }, - //ClassPaladin - new uint[] { _strength, _critical, _haste }, - //ClassHunter - new uint[] { _agility, _critical, _attackPower }, - //ClassRogue - new uint[] { _agility, _haste, _attackPower }, - //ClassPriest - Array.Empty(), - //ClassDeathKnight - new uint[] { _strength, _critical, _haste }, - //ClassShaman - new uint[] { _agility, _haste, _attackPower }, - //ClassMage - Array.Empty(), - //ClassWarlock - Array.Empty(), - //ClassUnk - Array.Empty(), - //ClassDruid - new uint[] { _strength, _agility, _haste } - }; - - - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - var randomSpells = triggeredSpells[(int)caster.GetClass()]; - if (randomSpells.Empty()) - return; - - uint spellId = randomSpells.SelectRandom(); - caster.CastSpell(caster, spellId, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 47770 - Roll Dice - class spell_item_decahedral_dwarven_dice : SpellScript - { - const uint TextDecahedralDwarvenDice = 26147; - - public override bool Validate(SpellInfo spellInfo) - { - if (!CliDB.BroadcastTextStorage.ContainsKey(TextDecahedralDwarvenDice)) - return false; - return true; - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - GetCaster().TextEmote(TextDecahedralDwarvenDice, GetHitUnit()); - - uint minimum = 1; - uint maximum = 100; - - GetCaster().ToPlayer().DoRandomRoll(minimum, maximum); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 23134 - Goblin Bomb - class spell_item_goblin_bomb_dispenser : SpellScript - { - const uint SpellSummonGoblinBomb = 13258; - const uint SpellMalfunctionExplosion = 13261; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellSummonGoblinBomb, SpellMalfunctionExplosion); - } - - void HandleDummy(uint effIndex) - { - Item item = GetCastItem(); - if (item != null) - GetCaster().CastSpell(GetCaster(), RandomHelper.randChance(95) ? SpellSummonGoblinBomb : SpellMalfunctionExplosion, item); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 46203 - Goblin Weather Machine - class spell_item_goblin_weather_machine : SpellScript - { - const uint SpellPersonalizedWeather1 = 46740; - const uint SpellPersonalizedWeather2 = 46739; - const uint SpellPersonalizedWeather3 = 46738; - const uint SpellPersonalizedWeather4 = 46736; - - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - - uint spellId = RandomHelper.RAND(SpellPersonalizedWeather1, SpellPersonalizedWeather2, SpellPersonalizedWeather3, SpellPersonalizedWeather4); - target.CastSpell(target, spellId, GetSpell()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - // 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success - // 22999 - Defibrillate (Goblin Jumper Cables Xl) have 50% chance on success - // 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success - [Script("spell_item_goblin_jumper_cables", 67, SpellGoblinJumperCablesFail)] - [Script("spell_item_goblin_jumper_cables_xl", 50, SpellGoblinJumperCablesXlFail)] - [Script("spell_item_gnomish_army_knife", 33, 0u)] - class spell_item_defibrillate_SpellScript : SpellScript - { - const uint SpellGoblinJumperCablesFail = 8338; - const uint SpellGoblinJumperCablesXlFail = 23055; - - byte _chance; - uint _failSpell; - - public spell_item_defibrillate_SpellScript(byte chance, uint failSpell) - { - _chance = chance; - _failSpell = failSpell; - } - - public override bool Validate(SpellInfo spellInfo) - { - return _failSpell == 0 || ValidateSpellInfo(_failSpell); - } - - void HandleScript(uint effIndex) - { - if (RandomHelper.randChance(_chance)) - { - PreventHitDefaultEffect(effIndex); - if (_failSpell != 0) - GetCaster().CastSpell(GetCaster(), _failSpell, GetCastItem()); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.Resurrect)); - } - } - - [Script] // 33896 - Desperate Defense - class spell_item_desperate_defense : AuraScript - { - const uint SpellDesperateRage = 33898; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDesperateRage); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellDesperateRage, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 2, AuraType.ProcTriggerSpell)); - } - } - - // http://www.wowhead.com/item=6522 Deviate Fish - [Script] // 8063 Deviate Fish - class spell_item_deviate_fish : SpellScript - { - const uint SpellSleepy = 8064; - const uint SpellInvigorate = 8065; - const uint SpellShrink = 8066; - const uint SpellPartyTime = 8067; - const uint SpellHealthySpirit = 8068; - const uint SpellRejuvenation = 8070; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellSleepy, SpellInvigorate, SpellShrink, SpellPartyTime, SpellHealthySpirit, SpellRejuvenation); - } - - void HandleDummy(uint effIndex) - { Unit caster = GetCaster(); - uint spellId = RandomHelper.RAND(SpellSleepy, SpellInvigorate, SpellShrink, SpellPartyTime, SpellHealthySpirit, SpellRejuvenation); caster.CastSpell(caster, spellId, true); } + } - public override void Register() + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// Item - 13503: Alchemist's Stone +// Item - 35748: Guardian's Alchemist Stone +// Item - 35749: Sorcerer's Alchemist Stone +// Item - 35750: Redeemer's Alchemist Stone +// Item - 35751: Assassin's Alchemist Stone +// Item - 44322: Mercurial Alchemist Stone +// Item - 44323: Indestructible Alchemist's Stone +// Item - 44324: Mighty Alchemist's Stone + +[Script] // 17619 - Alchemist Stone +class spell_item_alchemist_stone : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AlchemistStoneExtraHeal, SpellIds.AlchemistStoneExtraMana); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo().GetSpellInfo().SpellFamilyName == SpellFamilyNames.Potion; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + uint spellId = 0; + int amount = (int)(eventInfo.GetDamageInfo().GetDamage() * 0.4f); + + if (eventInfo.GetDamageInfo().GetSpellInfo().HasEffect(SpellEffectName.Heal)) + spellId = SpellIds.AlchemistStoneExtraHeal; + else if (eventInfo.GetDamageInfo().GetSpellInfo().HasEffect(SpellEffectName.Energize)) + spellId = SpellIds.AlchemistStoneExtraMana; + + if (spellId == 0) + return; + + Unit caster = eventInfo.GetActionTarget(); + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, amount); + caster.CastSpell(null, spellId, args); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// Item - 50351: Tiny Abomination in a Jar +// 71406 - Anger Capacitor + +// Item - 50706: Tiny Abomination in a Jar (Heroic) +// 71545 - Anger Capacitor +[Script("spell_item_tiny_abomination_in_a_jar", 8)] +[Script("spell_item_tiny_abomination_in_a_jar_hero", 7)] +class spell_item_anger_capacitor(uint stacks) : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MoteOfAnger, SpellIds.ManifestAngerMainHand, SpellIds.ManifestAngerOffHand); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + caster.CastSpell(null, SpellIds.MoteOfAnger, true); + Aura motes = caster.GetAura(SpellIds.MoteOfAnger); + if (motes == null || motes.GetStackAmount() < stacks) + return; + + caster.RemoveAurasDueToSpell(SpellIds.MoteOfAnger); + uint spellId = SpellIds.ManifestAngerMainHand; + Player player = caster.ToPlayer(); + if (player != null && player.GetWeaponForAttack(WeaponAttackType.OffAttack, true) != null && RandomHelper.randChance(50)) + spellId = SpellIds.ManifestAngerOffHand; + + caster.CastSpell(target, spellId, aurEff); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.MoteOfAnger); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 26400 - Arcane Shroud +class spell_item_arcane_shroud : AuraScript +{ + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + int diff = (int)GetUnitOwner().GetLevel() - 60; + if (diff > 0) + amount += 2 * diff; + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModThreat)); + } +} + +// Item - 31859: Darkmoon Card: Madness +[Script] // 39446 - Aura of Madness +class spell_item_aura_of_madness : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Sociopath, SpellIds.Delusional, SpellIds.Kleptomania, SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, + SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia) && CliDB.BroadcastTextStorage.ContainsKey(MiscConst.SayMadness); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + List[] triggeredSpells = + [ + //ClassNone + [], + //ClassWarrior + [ SpellIds.Sociopath, SpellIds.Delusional, SpellIds.Kleptomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.MartyrComplex ], + //ClassPaladin + [SpellIds.Sociopath, SpellIds.Delusional, SpellIds.Kleptomania, SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia ], + //ClassHunter + [SpellIds.Delusional, SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia ], + //ClassRogue + [SpellIds.Sociopath, SpellIds.Delusional, SpellIds.Kleptomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.MartyrComplex ], + //ClassPriest + [SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia ], + //ClassDeathKnight + [SpellIds.Sociopath, SpellIds.Delusional, SpellIds.Kleptomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.MartyrComplex ], + //ClassShaman + [SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia ], + //ClassMage + [SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia ], + //ClassWarlock + [SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia ], + //ClassUnk + [], + //ClassDruid + [SpellIds.Sociopath, SpellIds.Delusional, SpellIds.Kleptomania, SpellIds.Megalomania, SpellIds.Paranoia, SpellIds.Manic, SpellIds.Narcissism, SpellIds.MartyrComplex, SpellIds.Dementia ] + ]; + + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + uint spellId = triggeredSpells[(int)caster.GetClass()].SelectRandom(); + caster.CastSpell(caster, spellId, aurEff); + + if (RandomHelper.randChance(10)) + caster.Say(MiscConst.SayMadness); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 41404 - Dementia +class spell_item_dementia : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DementiaPos, SpellIds.DementiaNeg); + } + + void HandlePeriodicDummy(AuraEffect aurEff) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), RandomHelper.RAND(SpellIds.DementiaPos, SpellIds.DementiaNeg), aurEff); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodicDummy, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 24590 - Brittle Armor +class spell_item_brittle_armor : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BrittleArmor); + } + + void HandleScript(uint effIndex) + { + GetHitUnit().RemoveAuraFromStack(SpellIds.BrittleArmor); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 64411 - Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings) +class spell_item_blessing_of_ancient_kings : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ProtectionOfAncientKings); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() != null; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo == null || healInfo.GetHeal() == 0) + return; + + int absorb = (int)MathFunctions.CalculatePct(healInfo.GetHeal(), 15.0f); + AuraEffect protEff = eventInfo.GetProcTarget().GetAuraEffect(SpellIds.ProtectionOfAncientKings, 0, eventInfo.GetActor().GetGUID()); + if (protEff != null) { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + // The shield can grow to a maximum size of 20,000 damage absorbtion + protEff.SetAmount(Math.Min(protEff.GetAmount() + absorb, 20000)); + + // Refresh and return to prevent replacing the aura + protEff.GetBase().RefreshDuration(); + } + else + { + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, absorb); + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.ProtectionOfAncientKings, args); } } - class PartyTimeEmoteEvent : BasicEvent + public override void Register() { - const uint SpellPartyTime = 8067; + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - Player _player; +[Script] // 64415 Val'anyr Hammer of Ancient Kings - Equip Effect +class spell_item_valanyr_hammer_of_ancient_kings : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetHealInfo() != null && eventInfo.GetHealInfo().GetEffectiveHeal() > 0; + } - public PartyTimeEmoteEvent(Player player) + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] // 71564 - Deadly Precision +class spell_item_deadly_precision : AuraScript +{ + void HandleStackDrop(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().RemoveAuraFromStack(GetId(), GetTarget().GetGUID()); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleStackDrop, 0, AuraType.ModRating)); + } +} + +[Script] // 71563 - Deadly Precision Dummy +class spell_item_deadly_precision_dummy : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DeadlyPrecision); + } + + void HandleDummy(uint effIndex) + { + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.DeadlyPrecision, GetCastDifficulty()); + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.AddSpellMod(SpellValueMod.AuraStack, (int)spellInfo.StackAmount); + GetCaster().CastSpell(GetCaster(), spellInfo.Id, args); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.ApplyAura)); + } +} + +// Item - 50362: Deathbringer's Will +// 71519 - Item - Icecrown 25 Normal Melee Trinket + +// Item - 50363: Deathbringer's Will +// 71562 - Item - Icecrown 25 Heroic Melee Trinket +[Script("spell_item_deathbringers_will_normal", SpellIds.StrengthOfTheTaunka, SpellIds.AgilityOfTheVrykul, SpellIds.PowerOfTheTaunka, SpellIds.AimOfTheIronDwarves, SpellIds.SpeedOfTheVrykul)] +[Script("spell_item_deathbringers_will_heroic", SpellIds.StrengthOfTheTaunkaHero, SpellIds.AgilityOfTheVrykulHero, SpellIds.PowerOfTheTaunkaHero, SpellIds.AimOfTheIronDwarvesHero, SpellIds.SpeedOfTheVrykulHero)] +class spell_item_deathbringers_will(uint StrengthSpellId, uint AgilitySpellId, uint APSpellId, uint CriticalSpellId, uint HasteSpellId) : AuraScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(StrengthSpellId, AgilitySpellId, APSpellId, CriticalSpellId, HasteSpellId); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + List[] triggeredSpells = + [ + //ClassNone + [], + //ClassWarrior + [StrengthSpellId, CriticalSpellId, HasteSpellId ], + //ClassPaladin + [StrengthSpellId, CriticalSpellId, HasteSpellId ], + //ClassHunter + [AgilitySpellId, CriticalSpellId, APSpellId ], + //ClassRogue + [AgilitySpellId, HasteSpellId, APSpellId ], + //ClassPriest + [], + //ClassDeathKnight + [StrengthSpellId, CriticalSpellId, HasteSpellId ], + //ClassShaman + [AgilitySpellId, HasteSpellId, APSpellId ], + //ClassMage + [], + //ClassWarlock + [], + //ClassUnk + [], + //ClassDruid + [StrengthSpellId, AgilitySpellId, HasteSpellId] + ]; + + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + List randomSpells = triggeredSpells[(int)caster.GetClass()]; + if (randomSpells.Empty()) + return; + + uint spellId = randomSpells.SelectRandom(); + caster.CastSpell(caster, spellId, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 47770 - Roll Dice +class spell_item_decahedral_dwarven_dice : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (!CliDB.BroadcastTextStorage.ContainsKey(MiscConst.TextDecahedralDwarvenDice)) + return false; + return true; + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + GetCaster().TextEmote(MiscConst.TextDecahedralDwarvenDice, GetHitUnit()); + + uint minimum = 1; + uint maximum = 100; + + GetCaster().ToPlayer().DoRandomRoll(minimum, maximum); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 23134 - Goblin Bomb +class spell_item_goblin_bomb_dispenser : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SummonGoblinBomb, SpellIds.MalfunctionExplosion); + } + + void HandleDummy(uint effIndex) + { + Item item = GetCastItem(); + if (item != null) + GetCaster().CastSpell(GetCaster(), RandomHelper.randChance(95) ? SpellIds.SummonGoblinBomb : SpellIds.MalfunctionExplosion, item); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 46203 - Goblin Weather Machine +class spell_item_goblin_weather_machine : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + + uint spellId = RandomHelper.RAND(SpellIds.PersonalizedWeather1, SpellIds.PersonalizedWeather2, SpellIds.PersonalizedWeather3, SpellIds.PersonalizedWeather4); + target.CastSpell(target, spellId, GetSpell()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +// 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success +// 22999 - Defibrillate (Goblin Jumper Cables Xl) have 50% chance on success +// 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success +[Script("spell_item_goblin_jumper_cables", 67, SpellIds.GoblinJumperCablesFail)] +[Script("spell_item_goblin_jumper_cables_xl", 50, SpellIds.GoblinJumperCablesXlFail)] +[Script("spell_item_gnomish_army_knife", 33, 0)] +class spell_item_defibrillate(byte chance, uint failSpell) : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return failSpell == 0 || ValidateSpellInfo(failSpell); + } + + void HandleScript(uint effIndex) + { + if (RandomHelper.randChance(chance)) { - _player = player; + PreventHitDefaultEffect(effIndex); + if (failSpell != 0) + GetCaster().CastSpell(GetCaster(), failSpell, GetCastItem()); } + } + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.Resurrect)); + } +} + +[Script] // 33896 - Desperate Defense +class spell_item_desperate_defense : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DesperateRage); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.DesperateRage, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 2, AuraType.ProcTriggerSpell)); + } +} + +// http://www.wowhead.com/item=6522 Deviate Fish +[Script] // 8063 Deviate Fish +class spell_item_deviate_fish : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Sleepy, SpellIds.Invigorate, SpellIds.Shrink, SpellIds.PartyTime, SpellIds.HealthySpirit, SpellIds.Rejuvenation); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + uint spellId = RandomHelper.RAND(SpellIds.Sleepy, SpellIds.Invigorate, SpellIds.Shrink, SpellIds.PartyTime, SpellIds.HealthySpirit, SpellIds.Rejuvenation); + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_party_time : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Player player = GetOwner().ToPlayer(); + if (player == null) + return; + + player.m_Events.AddEventAtOffset(new PartyTimeEmoteEvent(player), RandomHelper.RAND(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15))); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } + + class PartyTimeEmoteEvent(Player player) : BasicEvent + { public override bool Execute(ulong time, uint diff) { - if (!_player.HasAura(SpellPartyTime)) + if (!player.HasAura(SpellIds.PartyTime)) return true; - if (_player.IsMoving()) - _player.HandleEmoteCommand(RandomHelper.RAND(Emote.OneshotApplaud, Emote.OneshotLaugh, Emote.OneshotCheer, Emote.OneshotChicken)); + if (player.IsMoving()) + player.HandleEmoteCommand(RandomHelper.RAND(Emote.OneshotApplaud, Emote.OneshotLaugh, Emote.OneshotCheer, Emote.OneshotChicken)); else - _player.HandleEmoteCommand(RandomHelper.RAND(Emote.OneshotApplaud, Emote.OneshotDancespecial, Emote.OneshotLaugh, Emote.OneshotCheer, Emote.OneshotChicken)); + player.HandleEmoteCommand(RandomHelper.RAND(Emote.OneshotApplaud, Emote.OneshotDancespecial, Emote.OneshotLaugh, Emote.OneshotCheer, Emote.OneshotChicken)); - _player.m_Events.AddEventAtOffset(this, RandomHelper.RAND(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15))); + player.m_Events.AddEventAtOffset(this, RandomHelper.RAND(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15))); - return false; // do not delete re-added event in EventProcessor.Update - } - } - - [Script] - class spell_item_party_time : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Player player = GetOwner().ToPlayer(); - if (player == null) - return; - - player.m_Events.AddEventAtOffset(new PartyTimeEmoteEvent(player), RandomHelper.RAND(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15))); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - struct DireBrewModels - { - public const uint ClothMale = 25229; - public const uint ClothFemale = 25233; - public const uint LeatherMale = 25230; - public const uint LeatherFemale = 25234; - public const uint MailMale = 25231; - public const uint MailFemale = 25235; - public const uint PlateMale = 25232; - public const uint PlateFemale = 25236; - } - - [Script] // 51010 - Dire Brew - class spell_item_dire_brew : AuraScript - { - void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - - uint model = 0; - Gender gender = target.GetGender(); - ChrClassesRecord chrClass = CliDB.ChrClassesStorage.LookupByKey(target.GetClass()); - if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Plate)) != 0) - model = gender == Gender.Male ? DireBrewModels.PlateMale : DireBrewModels.PlateFemale; - else if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Mail)) != 0) - model = gender == Gender.Male ? DireBrewModels.MailMale : DireBrewModels.MailFemale; - else if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Leather)) != 0) - model = gender == Gender.Male ? DireBrewModels.LeatherMale : DireBrewModels.LeatherFemale; - else if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Cloth)) != 0) - model = gender == Gender.Male ? DireBrewModels.ClothMale : DireBrewModels.ClothFemale; - - if (model != 0) - target.SetDisplayId(model); - } - - public override void Register() - { - AfterEffectApply.Add(new(AfterApply, 0, AuraType.Transform, AuraEffectHandleModes.Real)); - } - } - - [Script] // 59915 - Discerning Eye of the Beast Dummy - class spell_item_discerning_eye_beast_dummy : AuraScript - { - const uint SpellDiscerningEyeBeast = 59914; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDiscerningEyeBeast); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - eventInfo.GetActor().CastSpell(null, SpellDiscerningEyeBeast, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 71610, 71641 - Echoes of Light (Althor's Abacus) - class spell_item_echoes_of_light : SpellScript - { - void FilterTargets(List targets) - { - if (targets.Count < 2) - return; - - targets.Sort(new HealthPctOrderPred()); - - WorldObject target = targets.FirstOrDefault(); - targets.Clear(); - targets.Add(target); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - } - } - - [Script] // 30427 - Extract Gas (23821: Zapthrottle Mote Extractor) - class spell_item_extract_gas : AuraScript - { - void PeriodicTick(AuraEffect aurEff) - { - PreventDefaultAction(); - - // move loot to player inventory and despawn target - if (GetCaster() != null && GetCaster().IsPlayer() && - GetTarget().GetTypeId() == TypeId.Unit && - GetTarget().ToCreature().GetCreatureTemplate().CreatureType == CreatureType.GasCloud) - { - Player player = GetCaster().ToPlayer(); - Creature creature = GetTarget().ToCreature(); - CreatureDifficulty creatureDifficulty = creature.GetCreatureDifficulty(); - // missing lootid has been reported on startup - just return - if (creatureDifficulty.SkinLootID == 0) - return; - - player.AutoStoreLoot(creatureDifficulty.SkinLootID, LootStorage.Skinning, ItemContext.None, true); - creature.DespawnOrUnsummon(); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicTriggerSpell)); - } - } - - [Script] // 7434 - Fate Rune of Unsurpassed Vigor - class spell_item_fate_rune_of_unsurpassed_vigor : AuraScript - { - const uint SpellUnsurpassedVigor = 25733; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellUnsurpassedVigor); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellUnsurpassedVigor, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - //57426 - Fish Feast - //58465 - Gigantic Feast - //58474 - Small Feast - //66476 - Bountiful Feast - [Script("spell_item_great_feast", TextGreatFeast)] - [Script("spell_item_fish_feast", TextFishFeast)] - [Script("spell_item_gigantic_feast", TextGiganticFeast)] - [Script("spell_item_small_feast", TextSmallFeast)] - [Script("spell_item_bountiful_feast", TextBountifulFeast)] - class spell_item_feast : SpellScript - { - const uint TextGreatFeast = 31843; - const uint TextFishFeast = 31844; - const uint TextGiganticFeast = 31846; - const uint TextSmallFeast = 31845; - const uint TextBountifulFeast = 35153; - - uint _text; - - public spell_item_feast(uint text) - { - _text = text; - } - - public override bool Validate(SpellInfo spellInfo) - { - return CliDB.BroadcastTextStorage.ContainsKey(_text); - } - - void HandleScript(uint effIndex) - { - Unit caster = GetCaster(); - caster.TextEmote(_text, caster, false); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - // http://www.wowhead.com/item=47499 Flask of the North - [Script] // 67019 Flask of the North - class spell_item_flask_of_the_north : SpellScript - { - const uint SpellFlaskOfTheNorthSp = 67016; - const uint SpellFlaskOfTheNorthAp = 67017; - const uint SpellFlaskOfTheNorthStr = 67018; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFlaskOfTheNorthSp, SpellFlaskOfTheNorthAp, SpellFlaskOfTheNorthStr); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - List possibleSpells = new(); - switch (caster.GetClass()) - { - case Class.Warlock: - case Class.Mage: - case Class.Priest: - possibleSpells.Add(SpellFlaskOfTheNorthSp); - break; - case Class.Deathknight: - case Class.Warrior: - possibleSpells.Add(SpellFlaskOfTheNorthStr); - break; - case Class.Rogue: - case Class.Hunter: - possibleSpells.Add(SpellFlaskOfTheNorthAp); - break; - case Class.Druid: - case Class.Paladin: - possibleSpells.Add(SpellFlaskOfTheNorthSp); - possibleSpells.Add(SpellFlaskOfTheNorthStr); - break; - case Class.Shaman: - possibleSpells.Add(SpellFlaskOfTheNorthSp); - possibleSpells.Add(SpellFlaskOfTheNorthAp); - break; - } - - if (possibleSpells.Empty()) - { - Log.outWarn(LogFilter.Spells, $"Missing spells for class {caster.GetClass()} in script spell_item_flask_of_the_north"); - return; - } - - caster.CastSpell(caster, possibleSpells.SelectRandom(), true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // 39372 - Frozen Shadoweave - [Script] // Frozen Shadoweave set 3p bonus - class spell_item_frozen_shadoweave : AuraScript - { - const uint SpellShadowmend = 39373; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellShadowmend); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; - - Unit caster = eventInfo.GetActor(); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount())); - caster.CastSpell(null, SpellShadowmend, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - // http://www.wowhead.com/item=10645 Gnomish Death Ray - [Script] // 13280 Gnomish Death Ray - class spell_item_gnomish_death_ray : SpellScript - { - const uint SpellGnomishDeathRaySelf = 13493; - const uint SpellGnomishDeathRayTarget = 13279; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellGnomishDeathRaySelf, SpellGnomishDeathRayTarget); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - if (target != null) - { - if (RandomHelper.URand(0, 99) < 15) - caster.CastSpell(caster, SpellGnomishDeathRaySelf, true); // failure - else - caster.CastSpell(target, SpellGnomishDeathRayTarget, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // Item 10721: Gnomish Harm Prevention Belt - [Script] // 13234 - Harm Prevention Belt - class spell_item_harm_prevention_belt : AuraScript - { - const uint SpellForcefieldCollapse = 13235; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellForcefieldCollapse); - } - - void HandleProc(ProcEventInfo eventInfo) - { - GetTarget().CastSpell(null, SpellForcefieldCollapse, true); - } - - public override void Register() - { - OnProc.Add(new(HandleProc)); - } - } - - // Item - 49982: Heartpierce - // 71880 - Item - Icecrown 25 Normal Dagger Proc - - // Item - 50641: Heartpierce (Heroic) - // 71892 - Item - Icecrown 25 Heroic Dagger Proc - [Script("spell_item_heartpierce", SpellInvigorationEnergy, SpellInvigorationMana, SpellInvigorationRage, SpellInvigorationRp)] - [Script("spell_item_heartpierce_hero", SpellInvigorationEnergyHero, SpellInvigorationManaHero, SpellInvigorationRageHero, SpellInvigorationRpHero)] - class spell_item_heartpierce : AuraScript - { - const uint SpellInvigorationMana = 71881; - const uint SpellInvigorationEnergy = 71882; - const uint SpellInvigorationRage = 71883; - const uint SpellInvigorationRp = 71884; - - const uint SpellInvigorationRpHero = 71885; - const uint SpellInvigorationRageHero = 71886; - const uint SpellInvigorationEnergyHero = 71887; - const uint SpellInvigorationManaHero = 71888; - - uint _energy; - uint _mana; - uint _rage; - uint _runicPower; - - public spell_item_heartpierce(uint energy, uint mana, uint rage, uint runicPower) - { - _energy = energy; - _mana = mana; - _rage = rage; - _runicPower = runicPower; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_energy, _mana, _rage, _runicPower); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - - uint spellId; - switch (caster.GetPowerType()) - { - case PowerType.Mana: - spellId = _mana; - break; - case PowerType.Energy: - spellId = _energy; - break; - case PowerType.Rage: - spellId = _rage; - break; - // Death Knights can't use daggers, but oh well - case PowerType.RunicPower: - spellId = _runicPower; - break; - default: - return; - } - - caster.CastSpell(null, spellId, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 23645 - Hourglass Sand - class spell_item_hourglass_sand : SpellScript - { - const uint SpellBroodAfflictionBronze = 23170; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellBroodAfflictionBronze); - } - - void HandleDummy(uint effIndex) - { - GetCaster().RemoveAurasDueToSpell(SpellBroodAfflictionBronze); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 40971 - Bonus Healing (Crystal Spire of Karabor) - class spell_item_crystal_spire_of_karabor : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 0)); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - int pct = GetSpellInfo().GetEffect(0).CalcValue(); - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo != null) - { - Unit healTarget = healInfo.GetTarget(); - if (healTarget != null) - if (healTarget.GetHealth() - healInfo.GetEffectiveHeal() <= healTarget.CountPctFromMaxHealth(pct)) - return true; - } - - return false; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } - } - - // http://www.wowhead.com/item=27388 Mr. Pinchy - [Script] // 33060 Make a Wish - class spell_item_make_a_wish : SpellScript - { - const uint SpellMrPinchysBlessing = 33053; - const uint SpellSummonMightyMrPinchy = 33057; - const uint SpellSummonFuriousMrPinchy = 33059; - const uint SpellTinyMagicalCrawdad = 33062; - const uint SpellMrPinchysGift = 33064; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellMrPinchysBlessing, SpellSummonMightyMrPinchy, SpellSummonFuriousMrPinchy, SpellTinyMagicalCrawdad, SpellMrPinchysGift); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - uint spellId = SpellMrPinchysGift; - switch (RandomHelper.URand(1, 5)) - { - case 1: spellId = SpellMrPinchysBlessing; break; - case 2: spellId = SpellSummonMightyMrPinchy; break; - case 3: spellId = SpellSummonFuriousMrPinchy; break; - case 4: spellId = SpellTinyMagicalCrawdad; break; - } - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // Item - 27920: Mark of Conquest - // Item - 27921: Mark of Conquest - [Script] // 33510 - Health Restore - class spell_item_mark_of_conquest : AuraScript - { - const uint SpellMarkOfConquestEnergize = 39599; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellMarkOfConquestEnergize); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - if (eventInfo.GetTypeMask().HasFlag(ProcFlags.DealRangedAttack | ProcFlags.DealRangedAbility)) - { - // in that case, do not cast heal spell - PreventDefaultAction(); - // but mana instead - eventInfo.GetActor().CastSpell(null, SpellMarkOfConquestEnergize, aurEff); - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 26465 - Mercurial Shield - class spell_item_mercurial_shield : SpellScript - { - const uint SpellMercurialShield = 26464; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellMercurialShield); - } - - void HandleScript(uint effIndex) - { - GetHitUnit().RemoveAuraFromStack(SpellMercurialShield); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - // http://www.wowhead.com/item=32686 Mingo's Fortune Giblets - [Script] // 40802 Mingo's Fortune Generator - class spell_item_mingos_fortune_generator : SpellScript - { - uint[] CreateFortuneSpells = - { - 40804, 40805, 40806, 40807, 40808, - 40809, 40908, 40910, 40911, 40912, - 40913, 40914, 40915, 40916, 40918, - 40919, 40920, 40921, 40922, 40923 - }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(CreateFortuneSpells); - } - - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), CreateFortuneSpells.SelectRandom(), true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 71875, 71877 - Item - Black Bruise: Necrotic Touch Proc - class spell_item_necrotic_touch : AuraScript - { - const uint SpellItemNecroticTouchProc = 71879; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellItemNecroticTouchProc); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().IsAlive(); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount())); - GetTarget().CastSpell(null, SpellItemNecroticTouchProc, args); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - // http://www.wowhead.com/item=10720 Gnomish Net-o-Matic Projector - [Script] // 13120 Net-o-Matic - class spell_item_net_o_matic : SpellScript - { - const uint SpellNetOMaticTriggered1 = 16566; - const uint SpellNetOMaticTriggered2 = 13119; - const uint SpellNetOMaticTriggered3 = 13099; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellNetOMaticTriggered1, SpellNetOMaticTriggered2, SpellNetOMaticTriggered3); - } - - void HandleDummy(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - { - uint spellId = SpellNetOMaticTriggered3; - uint roll = RandomHelper.URand(0, 99); - if (roll < 2) // 2% for 30 sec self root (off-like chance unknown) - spellId = SpellNetOMaticTriggered1; - else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown) - spellId = SpellNetOMaticTriggered2; - - GetCaster().CastSpell(target, spellId, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // http://www.wowhead.com/item=8529 Noggenfogger Elixir - [Script] // 16589 Noggenfogger Elixir - class spell_item_noggenfogger_elixir : SpellScript - { - const uint SpellNoggenfoggerElixirTriggered1 = 16595; - const uint SpellNoggenfoggerElixirTriggered2 = 16593; - const uint SpellNoggenfoggerElixirTriggered3 = 16591; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellNoggenfoggerElixirTriggered1, SpellNoggenfoggerElixirTriggered2, SpellNoggenfoggerElixirTriggered3); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - uint spellId = SpellNoggenfoggerElixirTriggered3; - switch (RandomHelper.URand(1, 3)) - { - case 1: spellId = SpellNoggenfoggerElixirTriggered1; break; - case 2: spellId = SpellNoggenfoggerElixirTriggered2; break; - } - - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 29601 - Enlightenment (Pendant of the Violet Eye) - class spell_item_pendant_of_the_violet_eye : AuraScript - { - bool CheckProc(ProcEventInfo eventInfo) - { - Spell spell = eventInfo.GetProcSpell(); - if (spell != null && spell.GetPowerTypeCostAmount(PowerType.Mana) > 0) - return true; - - return false; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } - } - - [Script] // 26467 - Persistent Shield - class spell_item_persistent_shield : AuraScript - { - const uint SpellPersistentShieldTriggered = 26470; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellPersistentShieldTriggered); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetHealInfo() != null && eventInfo.GetHealInfo().GetHeal() != 0; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - int bp0 = (int)MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), 15); - - // Scarab Brooch does not replace stronger shields - AuraEffect shield = target.GetAuraEffect(SpellPersistentShieldTriggered, 0, caster.GetGUID()); - if (shield != null && shield.GetAmount() > bp0) - return; - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, bp0); - caster.CastSpell(target, SpellPersistentShieldTriggered, args); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - // 37381 - Pet Healing - // Hunter T5 2P Bonus - [Script] // Warlock T5 2P Bonus - class spell_item_pet_healing : AuraScript - { - const uint SpellHealthLink = 37382; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellHealthLink); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount())); - eventInfo.GetActor().CastSpell(null, SpellHealthLink, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 17512 - Piccolo of the Flaming Fire - class spell_item_piccolo_of_the_flaming_fire : SpellScript - { - void HandleScript(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - Player target = GetHitPlayer(); - if (target != null) - target.HandleEmoteCommand(Emote.StateDance); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 45043 - Power Circle (Shifting Naaru Sliver) - class spell_item_power_circle : AuraScript - { - const uint SpellLimitlessPower = 45044; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellLimitlessPower); - } - - bool CheckCaster(Unit target) - { - return target.GetGUID() == GetCasterGUID(); - } - - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().CastSpell(null, SpellLimitlessPower, true); - Aura buff = GetTarget().GetAura(SpellLimitlessPower); - buff?.SetDuration(GetDuration()); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellLimitlessPower); - } - - public override void Register() - { - DoCheckAreaTarget.Add(new(CheckCaster)); - - AfterEffectApply.Add(new(OnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - // http://www.wowhead.com/item=6657 Savory Deviate Delight - [Script] // 8213 Savory Deviate Delight - class spell_item_savory_deviate_delight : SpellScript - { - const uint SpellFlipOutMale = 8219; - const uint SpellFlipOutFemale = 8220; - const uint SpellYaaarrrrMale = 8221; - const uint SpellYaaarrrrFemale = 8222; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFlipOutMale, SpellFlipOutFemale, SpellYaaarrrrMale, SpellYaaarrrrFemale); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - uint spellId = 0; - switch (RandomHelper.URand(1, 2)) - { - // Flip Out - ninja - case 1: spellId = (caster.GetNativeGender() == Gender.Male ? SpellFlipOutMale : SpellFlipOutFemale); break; - // Yaaarrrr - pirate - case 2: spellId = (caster.GetNativeGender() == Gender.Male ? SpellYaaarrrrMale : SpellYaaarrrrFemale); break; - } - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // 48129 - Scroll of Recall - // 60320 - Scroll of Recall Ii - [Script] // 60321 - Scroll of Recall Iii - class spell_item_scroll_of_recall : SpellScript - { - const uint SpellScrollOfRecallI = 48129; - const uint SpellScrollOfRecallIi = 60320; - const uint SpellScrollOfRecallIii = 60321; - const uint SpellLost = 60444; - const uint SpellScrollOfRecallFailAlliance1 = 60323; - const uint SpellScrollOfRecallFailHorde1 = 60328; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - Unit caster = GetCaster(); - byte maxSafeLevel = 0; - switch (GetSpellInfo().Id) - { - case SpellScrollOfRecallI: // Scroll of Recall - maxSafeLevel = 40; - break; - case SpellScrollOfRecallIi: // Scroll of Recall Ii - maxSafeLevel = 70; - break; - case SpellScrollOfRecallIii: // Scroll of Recal Iii - maxSafeLevel = 80; - break; - default: - break; - } - - if (caster.GetLevel() > maxSafeLevel) - { - caster.CastSpell(caster, SpellLost, true); - - // Alliance from 60323 to 60330 - Horde from 60328 to 60335 - uint spellId = SpellScrollOfRecallFailAlliance1; - if (GetCaster().ToPlayer().GetTeam() == Team.Horde) - spellId = SpellScrollOfRecallFailHorde1; - - GetCaster().CastSpell(GetCaster(), spellId + RandomHelper.URand(0, 7), true); - - PreventHitDefaultEffect(effIndex); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); - } - } - - struct TransporterSpells - { - public const uint EvilTwin = 23445; - public const uint TransporterMalfunctionFire = 23449; - public const uint TransporterMalfunctionSmaller = 36893; - public const uint TransporterMalfunctionBigger = 36895; - public const uint TransporterMalfunctionChicken = 36940; - public const uint TransformHorde = 36897; - public const uint TransformAlliance = 36899; - public const uint SoulSplitEvil = 36900; - public const uint SoulSplitGood = 36901; - } - - [Script] // 23442 - Dimensional Ripper - Everlook - class spell_item_dimensional_ripper_everlook : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(TransporterSpells.TransporterMalfunctionFire, TransporterSpells.EvilTwin); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - int r = RandomHelper.IRand(0, 119); - if (r <= 70) // 7/12 success - return; - - Unit caster = GetCaster(); - - if (r < 100) // 4/12 evil twin - caster.CastSpell(caster, TransporterSpells.EvilTwin, true); - else // 1/12 fire - caster.CastSpell(caster, TransporterSpells.TransporterMalfunctionFire, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); - } - } - - [Script] // 36941 - Ultrasafe Transporter: Toshley's Station - class spell_item_ultrasafe_transporter : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(TransporterSpells.TransporterMalfunctionSmaller, TransporterSpells.TransporterMalfunctionBigger, TransporterSpells.SoulSplitEvil, TransporterSpells.SoulSplitGood, - TransporterSpells.TransformHorde, TransporterSpells.TransformAlliance, TransporterSpells.TransporterMalfunctionChicken, TransporterSpells.EvilTwin); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - if (!RandomHelper.randChance(50)) // 50% success - return; - - Unit caster = GetCaster(); - - uint spellId = 0; - switch (RandomHelper.URand(0, 6)) - { - case 0: - spellId = TransporterSpells.TransporterMalfunctionSmaller; - break; - case 1: - spellId = TransporterSpells.TransporterMalfunctionBigger; - break; - case 2: - spellId = TransporterSpells.SoulSplitEvil; - break; - case 3: - spellId = TransporterSpells.SoulSplitGood; - break; - case 4: - if (caster.ToPlayer().GetTeam() == Team.Alliance) - spellId = TransporterSpells.TransformHorde; - else - spellId = TransporterSpells.TransformAlliance; - break; - case 5: - spellId = TransporterSpells.TransporterMalfunctionChicken; - break; - case 6: - spellId = TransporterSpells.EvilTwin; - break; - default: - break; - } - - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); - } - } - - [Script] // 36890 - Dimensional Ripper - Area 52 - class spell_item_dimensional_ripper_area52 : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(TransporterSpells.TransporterMalfunctionBigger, TransporterSpells.SoulSplitEvil, TransporterSpells.SoulSplitGood, TransporterSpells.TransformHorde, TransporterSpells.TransformAlliance); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - if (!RandomHelper.randChance(50)) // 50% success - return; - - Unit caster = GetCaster(); - - uint spellId = 0; - switch (RandomHelper.URand(0, 3)) - { - case 0: - spellId = TransporterSpells.TransporterMalfunctionBigger; - break; - case 1: - spellId = TransporterSpells.SoulSplitEvil; - break; - case 2: - spellId = TransporterSpells.SoulSplitGood; - break; - case 3: - if (caster.ToPlayer().GetTeam() == Team.Alliance) - spellId = TransporterSpells.TransformHorde; - else - spellId = TransporterSpells.TransformAlliance; - break; - default: - break; - } - - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); - } - } - - [Script] // 71169 - Shadow's Fate (Shadowmourne questline) - class spell_item_unsated_craving : AuraScript - { - const uint NpcSindragosa = 36853; - - bool CheckProc(ProcEventInfo procInfo) - { - Unit caster = procInfo.GetActor(); - if (caster == null || !caster.IsPlayer()) - return false; - - Unit target = procInfo.GetActionTarget(); - if (target == null || target.GetTypeId() != TypeId.Unit || target.IsCritter() || (target.GetEntry() != NpcSindragosa && target.IsSummon())) - return false; - - return true; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } - } - - [Script] - class spell_item_shadows_fate : AuraScript - { - const uint SpellSoulFeast = 71203; - - void HandleProc(ProcEventInfo procInfo) - { - PreventDefaultAction(); - - Unit caster = procInfo.GetActor(); - Unit target = GetCaster(); - if (caster == null || target == null) - return; - - caster.CastSpell(target, SpellSoulFeast, TriggerCastFlags.FullMask); - } - - public override void Register() - { - OnProc.Add(new(HandleProc)); - } - } - - [Script] // 71903 - Item - Shadowmourne Legendary - class spell_item_shadowmourne : AuraScript - { - const uint SpellShadowmourneChaosBaneDamage = 71904; - const uint SpellShadowmourneSoulFragment = 71905; - const uint SpellShadowmourneChaosBaneBuff = 73422; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellShadowmourneChaosBaneDamage, SpellShadowmourneSoulFragment, SpellShadowmourneChaosBaneBuff); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - if (GetTarget().HasAura(SpellShadowmourneChaosBaneBuff)) // cant collect shards while under effect of Chaos Bane buff - return false; - return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().IsAlive(); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellShadowmourneSoulFragment, aurEff); - - // this can't be handled in AuraScript of SoulFragments because we need to know victim - Aura soulFragments = GetTarget().GetAura(SpellShadowmourneSoulFragment); - if (soulFragments != null) - { - if (soulFragments.GetStackAmount() >= 10) - { - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellShadowmourneChaosBaneDamage, aurEff); - soulFragments.Remove(); - } - } - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellShadowmourneSoulFragment); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 71905 - Soul Fragment - class spell_item_shadowmourne_soul_fragment : AuraScript - { - const uint SpellShadowmourneVisualLow = 72521; - const uint SpellShadowmourneVisualHigh = 72523; - const uint SpellShadowmourneChaosBaneBuff = 73422; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellShadowmourneVisualLow, SpellShadowmourneVisualHigh, SpellShadowmourneChaosBaneBuff); - } - - void OnStackChange(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - switch (GetStackAmount()) - { - case 1: - target.CastSpell(target, SpellShadowmourneVisualLow, true); - break; - case 6: - target.RemoveAurasDueToSpell(SpellShadowmourneVisualLow); - target.CastSpell(target, SpellShadowmourneVisualHigh, true); - break; - case 10: - target.RemoveAurasDueToSpell(SpellShadowmourneVisualHigh); - target.CastSpell(target, SpellShadowmourneChaosBaneBuff, true); - break; - default: - break; - } - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveAurasDueToSpell(SpellShadowmourneVisualLow); - target.RemoveAurasDueToSpell(SpellShadowmourneVisualHigh); - } - - public override void Register() - { - AfterEffectApply.Add(new(OnStackChange, 0, AuraType.ModStat, (AuraEffectHandleModes.Real | AuraEffectHandleModes.Reapply))); - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.ModStat, AuraEffectHandleModes.Real)); - } - } - - // http://www.wowhead.com/item=7734 Six Demon Bag - [Script] // 14537 Six Demon Bag - class spell_item_six_demon_bag : SpellScript - { - const uint SpellFrostbolt = 11538; - const uint SpellPolymorph = 14621; - const uint SpellSummonFelhoundMinion = 14642; - const uint SpellFireball = 15662; - const uint SpellChainLightning = 21179; - const uint SpellEnvelopingWinds = 25189; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFrostbolt, SpellPolymorph, SpellSummonFelhoundMinion, SpellFireball, SpellChainLightning, SpellEnvelopingWinds); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - if (target != null) - { - uint spellId; - uint rand = RandomHelper.URand(0, 99); - if (rand < 25) // Fireball (25% chance) - spellId = SpellFireball; - else if (rand < 50) // Frostball (25% chance) - spellId = SpellFrostbolt; - else if (rand < 70) // Chain Lighting (20% chance) - spellId = SpellChainLightning; - else if (rand < 80) // Polymorph (10% chance) - { - spellId = SpellPolymorph; - if (RandomHelper.URand(0, 100) <= 30) // 30% chance to self-cast - target = caster; - } - else if (rand < 95) // Enveloping Winds (15% chance) - spellId = SpellEnvelopingWinds; - else // Summon Felhund minion (5% chance) - { - spellId = SpellSummonFelhoundMinion; - target = caster; - } - - caster.CastSpell(target, spellId, GetCastItem()); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 59906 - Swift Hand of Justice Dummy - class spell_item_swift_hand_justice_dummy : AuraScript - { - const uint SpellSwiftHandOfJusticeHeal = 59913; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellSwiftHandOfJusticeHeal); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActor(); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)caster.CountPctFromMaxHealth(aurEff.GetAmount())); - caster.CastSpell(null, SpellSwiftHandOfJusticeHeal, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 28862 - The Eye of Diminution - class spell_item_the_eye_of_diminution : AuraScript - { - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - int diff = (int)(GetUnitOwner().GetLevel() - 60); - if (diff > 0) - amount += diff; - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModThreat)); - } - } - - // http://www.wowhead.com/item=44012 Underbelly Elixir - [Script] // 59640 Underbelly Elixir - class spell_item_underbelly_elixir : SpellScript - { - const uint SpellUnderbellyElixirTriggered1 = 59645; - const uint SpellUnderbellyElixirTriggered2 = 59831; - const uint SpellUnderbellyElixirTriggered3 = 59843; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellUnderbellyElixirTriggered1, SpellUnderbellyElixirTriggered2, SpellUnderbellyElixirTriggered3); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - uint spellId = SpellUnderbellyElixirTriggered3; - switch (RandomHelper.URand(1, 3)) - { - case 1: spellId = SpellUnderbellyElixirTriggered1; break; - case 2: spellId = SpellUnderbellyElixirTriggered2; break; - } - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 126755 - Wormhole: Pandaria - class spell_item_wormhole_pandaria : SpellScript - { - uint[] WormholeTargetLocations = - { - 126756, //SpellWormholePandariaIsleOfReckoning - 126757, //SpellWormholePandariaKunlaiUnderwater - 126758, //SpellWormholePandariaSraVess - 126759, //SpellWormholePandariaRikkitunVillage - 126760, //SpellWormholePandariaZanvessTree - 126761, //SpellWormholePandariaAnglersWharf - 126762, //SpellWormholePandariaCraneStatue - 126763, //SpellWormholePandariaEmperorsOmen - 126764 //SpellWormholePandariaWhitepetalLake - }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(WormholeTargetLocations); - } - - void HandleTeleport(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - uint spellId = WormholeTargetLocations.SelectRandom(); - GetCaster().CastSpell(GetHitUnit(), spellId, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleTeleport, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 47776 - Roll 'dem Bones - class spell_item_worn_troll_dice : SpellScript - { - const uint TextWornTrollDice = 26152; - - public override bool Validate(SpellInfo spellInfo) - { - if (!CliDB.BroadcastTextStorage.ContainsKey(TextWornTrollDice)) - return false; - return true; - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - GetCaster().TextEmote(TextWornTrollDice, GetHitUnit()); - - uint minimum = 1; - uint maximum = 6; - - // roll twice - GetCaster().ToPlayer().DoRandomRoll(minimum, maximum); - GetCaster().ToPlayer().DoRandomRoll(minimum, maximum); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_item_red_rider_air_rifle : SpellScript - { - const uint SpellAirRifleHoldVisual = 65582; - const uint SpellAirRifleShoot = 67532; - const uint SpellAirRifleShootSelf = 65577; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellAirRifleHoldVisual, SpellAirRifleShoot, SpellAirRifleShootSelf); - } - - void HandleScript(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - if (target != null) - { - caster.CastSpell(caster, SpellAirRifleHoldVisual, true); - // needed because this spell shares Gcd with its triggered spells (which must not be cast with triggered flag) - Player player = caster.ToPlayer(); - if (player != null) - player.GetSpellHistory().CancelGlobalCooldown(GetSpellInfo()); - if (RandomHelper.URand(0, 4) != 0) - caster.CastSpell(target, SpellAirRifleShoot, false); - else - caster.CastSpell(caster, SpellAirRifleShootSelf, false); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_item_book_of_glyph_mastery : SpellScript - { - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - SpellCastResult CheckRequirement() - { - if (SkillDiscovery.HasDiscoveredAllSpells(GetSpellInfo().Id, GetCaster().ToPlayer())) - { - SetCustomCastResultMessage(SpellCustomErrors.LearnedEverything); - return SpellCastResult.CustomError; - } - - return SpellCastResult.SpellCastOk; - } - - void HandleScript(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - uint spellId = GetSpellInfo().Id; - - // learn random explicit discovery recipe (if any) - uint discoveredSpellId = SkillDiscovery.GetExplicitDiscoverySpell(spellId, caster); - if (discoveredSpellId != 0) - caster.LearnSpell(discoveredSpellId, false); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckRequirement)); - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] - class spell_item_gift_of_the_harvester : SpellScript - { - const uint NpcGhoul = 28845; - const uint MaxGhouls = 5; - - SpellCastResult CheckRequirement() - { - List ghouls = new(); - GetCaster().GetAllMinionsByEntry(ghouls, NpcGhoul); - if (ghouls.Count >= MaxGhouls) - { - SetCustomCastResultMessage(SpellCustomErrors.TooManyGhouls); - return SpellCastResult.CustomError; - } - - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckRequirement)); - } - } - - [Script] - class spell_item_map_of_the_geyser_fields : SpellScript - { - const uint NpcSouthSinkhole = 25664; - const uint NpcNortheastSinkhole = 25665; - const uint NpcNorthwestSinkhole = 25666; - - SpellCastResult CheckSinkholes() - { - Unit caster = GetCaster(); - if (caster.FindNearestCreature(NpcSouthSinkhole, 30.0f, true) != null || - caster.FindNearestCreature(NpcNortheastSinkhole, 30.0f, true) != null || - caster.FindNearestCreature(NpcNorthwestSinkhole, 30.0f, true) != null) - return SpellCastResult.SpellCastOk; - - SetCustomCastResultMessage(SpellCustomErrors.MustBeCloseToSinkhole); - return SpellCastResult.CustomError; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckSinkholes)); - } - } - - [Script] - class spell_item_vanquished_clutches : SpellScript - { - const uint SpellCrusher = 64982; - const uint SpellConstrictor = 64983; - const uint SpellCorruptor = 64984; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellCrusher, SpellConstrictor, SpellCorruptor); - } - - void HandleDummy(uint effIndex) - { - uint spellId = RandomHelper.RAND(SpellCrusher, SpellConstrictor, SpellCorruptor); - Unit caster = GetCaster(); - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_ashbringer : SpellScript - { - uint[] AshbringerSounds = - { - 8906, // "I was pure once" - 8907, // "Fought for righteousness" - 8908, // "I was once called Ashbringer" - 8920, // "Betrayed by my order" - 8921, // "Destroyed by Kel'Thuzad" - 8922, // "Made to serve" - 8923, // "My son watched me die" - 8924, // "Crusades fed his rage" - 8925, // "Truth is unknown to him" - 8926, // "Scarlet Crusade is pure no longer" - 8927, // "Balnazzar's crusade corrupted my son" - 8928 // "Kill them all!" - }; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void OnDummyEffect(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - - Player player = GetCaster().ToPlayer(); - uint sound_id = RandomHelper.RAND(AshbringerSounds); - - // Ashbringers effect (spellID 28441) retriggers every 5 seconds, with a chance of making it say one of the above 12 sounds - if (RandomHelper.URand(0, 60) < 1) - player.PlayDirectSound(sound_id, player); - } - - public override void Register() - { - OnEffectHit.Add(new(OnDummyEffect, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 58886 - Food - class spell_magic_eater_food : AuraScript - { - const uint SpellWildMagic = 58891; - const uint SpellWellFed1 = 57288; - const uint SpellWellFed2 = 57139; - const uint SpellWellFed3 = 57111; - const uint SpellWellFed4 = 57286; - const uint SpellWellFed5 = 57291; - - void HandleTriggerSpell(AuraEffect aurEff) - { - PreventDefaultAction(); - Unit target = GetTarget(); - switch (RandomHelper.URand(0, 5)) - { - case 0: - target.CastSpell(target, SpellWildMagic, true); - break; - case 1: - target.CastSpell(target, SpellWellFed1, true); - break; - case 2: - target.CastSpell(target, SpellWellFed2, true); - break; - case 3: - target.CastSpell(target, SpellWellFed3, true); - break; - case 4: - target.CastSpell(target, SpellWellFed4, true); - break; - case 5: - target.CastSpell(target, SpellWellFed5, true); - break; - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleTriggerSpell, 1, AuraType.PeriodicTriggerSpell)); - } - } - - [Script] - class spell_item_nigh_invulnerability : SpellScript - { - const uint SpellNighInvulnerability = 30456; - const uint SpellCompleteVulnerability = 30457; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellNighInvulnerability, SpellCompleteVulnerability); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Item castItem = GetCastItem(); - if (castItem != null) - { - if (RandomHelper.randChance(86)) // Nigh-Invulnerability - success - caster.CastSpell(caster, SpellNighInvulnerability, castItem); - else // Complete Vulnerability - backfire in 14% casts - caster.CastSpell(caster, SpellCompleteVulnerability, castItem); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_poultryizer : SpellScript - { - const uint SpellPoultryizerSuccess = 30501; - const uint SpellPoultryizerBackfire = 30504; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellPoultryizerSuccess, SpellPoultryizerBackfire); - } - - void HandleDummy(uint effIndex) - { - if (GetCastItem() != null && GetHitUnit() != null) - GetCaster().CastSpell(GetHitUnit(), RandomHelper.randChance(80) ? SpellPoultryizerSuccess : SpellPoultryizerBackfire, GetCastItem()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_demon_broiled_surprise : SpellScript - { - const uint QuestSuperHotStew = 11379; - const uint SpellCreateDemonBroiledSurprise = 43753; - const uint NpcAbyssalFlamebringer = 19973; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellCreateDemonBroiledSurprise) && - ObjectMgr.GetCreatureTemplate(NpcAbyssalFlamebringer) != null && - ObjectMgr.GetQuestTemplate(QuestSuperHotStew) != null; - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) - { - Unit player = GetCaster(); - player.CastSpell(player, SpellCreateDemonBroiledSurprise, false); - } - - SpellCastResult CheckRequirement() - { - Player player = GetCaster().ToPlayer(); - if (player.GetQuestStatus(QuestSuperHotStew) != QuestStatus.Incomplete) - return SpellCastResult.CantDoThatRightNow; - - Creature creature = player.FindNearestCreature(NpcAbyssalFlamebringer, 10, false); - if (creature != null) - if (creature.IsDead()) - return SpellCastResult.SpellCastOk; - return SpellCastResult.NotHere; - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); - OnCheckCast.Add(new(CheckRequirement)); - } - } - - [Script] - class spell_item_complete_raptor_capture : SpellScript - { - const uint SpellRaptorCaptureCredit = 42337; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellRaptorCaptureCredit); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - if (GetHitCreature() != null) - { - GetHitCreature().DespawnOrUnsummon(); - - //cast spell Raptor Capture Credit - caster.CastSpell(caster, SpellRaptorCaptureCredit, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_impale_leviroth : SpellScript - { - const uint NpcLeviroth = 26452; - const uint SpellLevirothSelfImpale = 49882; - - public override bool Validate(SpellInfo spell) - { - if (ObjectMgr.GetCreatureTemplate(NpcLeviroth) == null) - return false; - return true; - } - - void HandleDummy(uint effIndex) - { - Creature target = GetHitCreature(); - if (target != null) - if (target.GetEntry() == NpcLeviroth && !target.HealthBelowPct(95)) - { - target.CastSpell(target, SpellLevirothSelfImpale, true); - target.ResetPlayerDamageReq(); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 23725 - Gift of Life - class spell_item_lifegiving_gem : SpellScript - { - const uint SpellGiftOfLife1 = 23782; - const uint SpellGiftOfLife2 = 23783; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellGiftOfLife1, SpellGiftOfLife2); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - caster.CastSpell(caster, SpellGiftOfLife1, true); - caster.CastSpell(caster, SpellGiftOfLife2, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_nitro_boosts : SpellScript - { - const uint SpellNitroBoostsSuccess = 54861; - const uint SpellNitroBoostsBackfire = 54621; - - public override bool Load() - { - return GetCastItem() != null; - } - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellNitroBoostsSuccess, SpellNitroBoostsBackfire); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - bool success = true; - if (!caster.GetMap().IsDungeon()) - success = RandomHelper.randChance(95); // nitro boosts can only fail in flying-enabled locations on 3.3.5 - caster.CastSpell(caster, success ? SpellNitroBoostsSuccess : SpellNitroBoostsBackfire, GetCastItem()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_nitro_boosts_backfire : AuraScript - { - const uint SpellNitroBoostsParachute = 54649; - - float lastZ = MapConst.InvalidHeight; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellNitroBoostsParachute); - } - - void HandleApply(AuraEffect effect, AuraEffectHandleModes mode) - { - lastZ = GetTarget().GetPositionZ(); - } - - void HandlePeriodicDummy(AuraEffect effect) - { - PreventDefaultAction(); - float curZ = GetTarget().GetPositionZ(); - if (curZ < lastZ) - { - if (RandomHelper.randChance(80)) // we don't have enough sniffs to verify this, guesstimate - GetTarget().CastSpell(GetTarget(), SpellNitroBoostsParachute, effect); - GetAura().Remove(); - } - else - lastZ = curZ; - } - - public override void Register() - { - OnEffectApply.Add(new(HandleApply, 1, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); - OnEffectPeriodic.Add(new(HandlePeriodicDummy, 1, AuraType.PeriodicTriggerSpell)); - } - } - - [Script] - class spell_item_rocket_boots : SpellScript - { - const uint SpellRocketBootsProc = 30452; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellRocketBootsProc); - } - - void HandleDummy(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - caster.GetSpellHistory().ResetCooldown(SpellRocketBootsProc); - caster.CastSpell(caster, SpellRocketBootsProc, true); - } - - SpellCastResult CheckCast() - { - if (GetCaster().IsInWater()) - return SpellCastResult.OnlyAbovewater; - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 67489 - Runic Healing Injector - class spell_item_runic_healing_injector : SpellScript - { - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleHeal(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - if (caster != null) - if (caster.HasSkill(SkillType.Engineering)) - SetHitHeal((int)(GetHitHeal() * 1.25f)); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHeal, 0, SpellEffectName.Heal)); - } - } - - [Script] - class spell_item_pygmy_oil : SpellScript - { - const uint SpellPygmyOilPygmyAura = 53806; - const uint SpellPygmyOilSmallerAura = 53805; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellPygmyOilPygmyAura, SpellPygmyOilSmallerAura); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Aura aura = caster.GetAura(SpellPygmyOilPygmyAura); - if (aura != null) - aura.RefreshDuration(); - else - { - aura = caster.GetAura(SpellPygmyOilSmallerAura); - if (aura == null || aura.GetStackAmount() < 5 || !RandomHelper.randChance(50)) - caster.CastSpell(caster, SpellPygmyOilSmallerAura, true); - else - { - aura.Remove(); - caster.CastSpell(caster, SpellPygmyOilPygmyAura, true); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_unusual_compass : SpellScript - { - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - caster.SetFacingTo(RandomHelper.FRand(0.0f, 2.0f * (float)(MathF.PI))); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_chicken_cover : SpellScript - { - const uint SpellChickenNet = 51959; - const uint SpellCaptureChickenEscape = 51037; - const uint QuestChickenParty = 12702; - const uint QuestFlownTheCoop = 12532; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellChickenNet, SpellCaptureChickenEscape) && - ObjectMgr.GetQuestTemplate(QuestChickenParty) != null && - ObjectMgr.GetQuestTemplate(QuestFlownTheCoop) != null; - } - - void HandleDummy(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - Unit target = GetHitUnit(); - if (target != null) - { - if (!target.HasAura(SpellChickenNet) && (caster.GetQuestStatus(QuestChickenParty) == QuestStatus.Incomplete || caster.GetQuestStatus(QuestFlownTheCoop) == QuestStatus.Incomplete)) - { - caster.CastSpell(caster, SpellCaptureChickenEscape, true); - target.KillSelf(); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_muisek_vessel : SpellScript - { - void HandleDummy(uint effIndex) - { - Creature target = GetHitCreature(); - if (target != null) - if (target.IsDead()) - target.DespawnOrUnsummon(); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] - class spell_item_greatmothers_soulcatcher : SpellScript - { - const uint SpellForceCastSummonGnomeSoul = 46486; - - void HandleDummy(uint effIndex) - { - if (GetHitUnit() != null) - GetCaster().CastSpell(GetCaster(), SpellForceCastSummonGnomeSoul); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // Item - 49310: Purified Shard of the Scale - // 69755 - Purified Shard of the Scale - Equip Effect - - // Item - 49488: Shiny Shard of the Scale - // 69739 - Shiny Shard of the Scale - Equip Effect - [Script("spell_item_purified_shard_of_the_scale", 69733, 69729)] - [Script("spell_item_shiny_shard_of_the_scale", 69734, 69730)] - class spell_item_shard_of_the_scale : AuraScript - { - uint _healProc; - uint _damageProc; - - public spell_item_shard_of_the_scale(uint healProc, uint damageProc) - { - _healProc = healProc; - _damageProc = damageProc; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_healProc, _damageProc); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - if (eventInfo.GetTypeMask().HasFlag(ProcFlags.DealHelpfulSpell)) - caster.CastSpell(target, _healProc, aurEff); - - if (eventInfo.GetTypeMask().HasFlag(ProcFlags.DealHarmfulSpell)) - caster.CastSpell(target, _damageProc, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] - class spell_item_soul_preserver : AuraScript - { - const uint SpellSoulPreserverDruid = 60512; - const uint SpellSoulPreserverPaladin = 60513; - const uint SpellSoulPreserverPriest = 60514; - const uint SpellSoulPreserverShaman = 60515; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellSoulPreserverDruid, SpellSoulPreserverPaladin, SpellSoulPreserverPriest, SpellSoulPreserverShaman); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActor(); - - switch (caster.GetClass()) - { - case Class.Druid: - caster.CastSpell(caster, SpellSoulPreserverDruid, aurEff); - break; - case Class.Paladin: - caster.CastSpell(caster, SpellSoulPreserverPaladin, aurEff); - break; - case Class.Priest: - caster.CastSpell(caster, SpellSoulPreserverPriest, aurEff); - break; - case Class.Shaman: - caster.CastSpell(caster, SpellSoulPreserverShaman, aurEff); - break; - default: - break; - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - // Item - 34678: Shattered Sun Pendant of Acumen - // 45481 - Sunwell Exalted Caster Neck - - // Item - 34679: Shattered Sun Pendant of Might - // 45482 - Sunwell Exalted Melee Neck - - // Item - 34680: Shattered Sun Pendant of Resolve - // 45483 - Sunwell Exalted Tank Neck - - // Item - 34677: Shattered Sun Pendant of Restoration - // 45484 Sunwell Exalted Healer Neck - [Script("spell_item_sunwell_exalted_caster_neck", 45479, 45429)] // Light's Wrath if Exalted by Aldor, Arcane Bolt if Exalted by Scryers - [Script("spell_item_sunwell_exalted_melee_neck", 45480, 45428)] // Light's Strength if Exalted by Aldor, Arcane Strike if Exalted by Scryers - [Script("spell_item_sunwell_exalted_tank_neck", 45432, 45431)] //Light's Ward if Exalted by Aldor, Arcane Insight if Exalted by Scryers - [Script("spell_item_sunwell_exalted_healer_neck", 45478, 45430)] //Light's Salvation if Exalted by Aldor, Arcane Surge if Exalted by Scryers - class spell_item_sunwell_neck : AuraScript - { - const uint FactionAldor = 932; - const uint FactionScryers = 934; - - uint _aldor; - uint _scryers; - - public spell_item_sunwell_neck(uint aldor, uint scryers) - { - _aldor = aldor; - _scryers = scryers; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_aldor, _scryers) && - CliDB.FactionStorage.ContainsKey(FactionAldor) && - CliDB.FactionStorage.ContainsKey(FactionScryers); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - if (!eventInfo.GetActor().IsPlayer()) - return false; - return true; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Player player = eventInfo.GetActor().ToPlayer(); - Unit target = eventInfo.GetProcTarget(); - - // Aggression checks are in the spell system... just cast and forget - if (player.GetReputationRank(FactionAldor) == ReputationRank.Exalted) - player.CastSpell(target, _aldor, aurEff); - - if (player.GetReputationRank(FactionScryers) == ReputationRank.Exalted) - player.CastSpell(target, _scryers, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] - class spell_item_toy_train_set_pulse : SpellScript - { - void HandleDummy(uint index) - { - Player target = GetHitUnit().ToPlayer(); - if (target != null) - { - target.HandleEmoteCommand(Emote.OneshotTrain); - var soundEntry = DB2Mgr.GetTextSoundEmoteFor((uint)TextEmotes.Train, target.GetRace(), target.GetNativeGender(), target.GetClass()); - if (soundEntry != null) - target.PlayDistanceSound(soundEntry.SoundId); - } - } - - void HandleTargets(List targetList) - { - targetList.RemoveAll(obj => !obj.IsPlayer()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); - OnObjectAreaTargetSelect.Add(new(HandleTargets, SpellConst.EffectAll, Targets.UnitSrcAreaAlly)); - } - } - - [Script] - class spell_item_death_choice : AuraScript - { - const uint SpellDeathChoiceNormalAura = 67702; - const uint SpellDeathChoiceNormalAgility = 67703; - const uint SpellDeathChoiceNormalStrength = 67708; - const uint SpellDeathChoiceHeroicAura = 67771; - const uint SpellDeathChoiceHeroicAgility = 67772; - const uint SpellDeathChoiceHeroicStrength = 67773; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDeathChoiceNormalStrength, SpellDeathChoiceNormalAgility, SpellDeathChoiceHeroicStrength, SpellDeathChoiceHeroicAgility); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActor(); - float str = caster.GetStat(Stats.Strength); - float agi = caster.GetStat(Stats.Agility); - - switch (aurEff.GetId()) - { - case SpellDeathChoiceNormalAura: - { - if (str > agi) - caster.CastSpell(caster, SpellDeathChoiceNormalStrength, aurEff); - else - caster.CastSpell(caster, SpellDeathChoiceNormalAgility, aurEff); - break; - } - case SpellDeathChoiceHeroicAura: - { - if (str > agi) - caster.CastSpell(caster, SpellDeathChoiceHeroicStrength, aurEff); - else - caster.CastSpell(caster, SpellDeathChoiceHeroicAgility, aurEff); - break; - } - default: - break; - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script("spell_item_lightning_capacitor", 37658, 37661)] // Lightning Capacitor - [Script("spell_item_thunder_capacitor", 54842, 54843)] // Thunder Capacitor - [Script("spell_item_toc25_normal_caster_trinket", 67713, 67714)] // Item - Coliseum 25 Normal Caster Trinket - [Script("spell_item_toc25_heroic_caster_trinket", 67759, 67760)] // Item - Coliseum 25 Heroic Caster Trinket - class spell_item_trinket_stack_AuraScript : AuraScript - { - uint _stackSpell; - uint _triggerSpell; - - public spell_item_trinket_stack_AuraScript(uint stackSpell, uint triggerSpell) - { - _stackSpell = stackSpell; - _triggerSpell = triggerSpell; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_stackSpell, _triggerSpell); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActor(); - - caster.CastSpell(caster, _stackSpell, aurEff); // cast the stack - - Aura dummy = caster.GetAura(_stackSpell); // retrieve aura - - //dont do anything if it's not the right amount of stacks; - if (dummy == null || dummy.GetStackAmount() < aurEff.GetAmount()) - return; - - // if right amount, Remove the aura and cast real trigger - caster.RemoveAurasDueToSpell(_stackSpell); - Unit target = eventInfo.GetActionTarget(); - if (target != null) - caster.CastSpell(target, _triggerSpell, aurEff); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(_stackSpell); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - [Script] // 57345 - Darkmoon Card: Greatness - class spell_item_darkmoon_card_greatness : AuraScript - { - const uint SpellDarkmoonCardStrength = 60229; - const uint SpellDarkmoonCardAgility = 60233; - const uint SpellDarkmoonCardIntellect = 60234; - const uint SpellDarkmoonCardVersatility = 60235; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellDarkmoonCardStrength, SpellDarkmoonCardAgility, SpellDarkmoonCardIntellect, SpellDarkmoonCardVersatility); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActor(); - float str = caster.GetStat(Stats.Strength); - float agi = caster.GetStat(Stats.Agility); - float intl = caster.GetStat(Stats.Intellect); - float vers = 0.0f; // caster.GetStat(StatVersatility); - float stat = 0.0f; - - uint spellTrigger = SpellDarkmoonCardStrength; - - if (str > stat) - { - spellTrigger = SpellDarkmoonCardStrength; - stat = str; - } - - if (agi > stat) - { - spellTrigger = SpellDarkmoonCardAgility; - stat = agi; - } - - if (intl > stat) - { - spellTrigger = SpellDarkmoonCardIntellect; - stat = intl; - } - - if (vers > stat) - spellTrigger = SpellDarkmoonCardVersatility; - - caster.CastSpell(caster, spellTrigger, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 27522,40336 - Mana Drain - class spell_item_mana_drain : AuraScript - { - const uint SpellManaDrainEnergize = 29471; - const uint SpellManaDrainLeech = 27526; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellManaDrainEnergize, SpellManaDrainLeech); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetActionTarget(); - - if (caster.IsAlive()) - caster.CastSpell(caster, SpellManaDrainEnergize, aurEff); - - if (target != null && target.IsAlive()) - caster.CastSpell(target, SpellManaDrainLeech, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 51640 - Taunt Flag Targeting - class spell_item_taunt_flag_targeting : SpellScript - { - const uint SpellTauntFlag = 51657; - const uint EmotePlantsFlag = 28008; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellTauntFlag) && - CliDB.BroadcastTextStorage.ContainsKey(EmotePlantsFlag); - } - - void FilterTargets(List targets) - { - targets.RemoveAll(obj => !obj.IsPlayer() && obj.GetTypeId() != TypeId.Corpse); - - if (targets.Empty()) - { - FinishCast(SpellCastResult.NoValidTargets); - return; - } - - targets.RandomResize(1); - } - - void HandleDummy(uint effIndex) - { - // we *really* want the unit implementation here - // it sends a packet like seen on sniff - GetCaster().TextEmote(EmotePlantsFlag, GetHitUnit(), false); - - GetCaster().CastSpell(GetHitUnit(), SpellTauntFlag, true); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.CorpseSrcAreaEnemy)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 29830 - Mirren's Drinking Hat - class spell_item_mirrens_drinking_hat : SpellScript - { - const uint SpellLochModanLager = 29827; - const uint SpellStouthammerLite = 29828; - const uint SpellAeriePeakPaleAle = 29829; - - void HandleScriptEffect(uint effIndex) - { - uint spellId; - switch (RandomHelper.URand(1, 6)) - { - case 1: - case 2: - case 3: - spellId = SpellLochModanLager; break; - case 4: - case 5: - spellId = SpellStouthammerLite; break; - case 6: - spellId = SpellAeriePeakPaleAle; break; - default: - return; - } - - Unit caster = GetCaster(); - caster.CastSpell(caster, spellId, GetSpell()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 13180 - Gnomish Mind Control Cap - class spell_item_mind_control_cap : SpellScript - { - const uint RollChanceDullard = 32; - const uint RollChanceNoBackfire = 95; - const uint SpellGnomishMindControlCap = 13181; - const uint SpellDullard = 67809; - - public override bool Load() - { - return GetCastItem() != null; - } - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellGnomishMindControlCap, SpellDullard); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - if (target != null) - { - if (RandomHelper.randChance(RollChanceNoBackfire)) - caster.CastSpell(target, RandomHelper.randChance(RollChanceDullard) ? SpellDullard : SpellGnomishMindControlCap, GetCastItem()); - else - target.CastSpell(caster, SpellGnomishMindControlCap, true); // backfire - 5% chance - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 8344 - Universal Remote (Gnomish Universal Remote) - class spell_item_universal_remote : SpellScript - { - const uint SpellControlMachine = 8345; - const uint SpellMobilityMalfunction = 8346; - const uint SpellTargetLock = 8347; - - public override bool Load() - { - return GetCastItem() != null; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellControlMachine, SpellMobilityMalfunction, SpellTargetLock); - } - - void HandleDummy(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - { - uint chance = RandomHelper.URand(0, 99); - if (chance < 15) - GetCaster().CastSpell(target, SpellTargetLock, GetCastItem()); - else if (chance < 25) - GetCaster().CastSpell(target, SpellMobilityMalfunction, GetCastItem()); - else - GetCaster().CastSpell(target, SpellControlMachine, GetCastItem()); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // Item - 19950: Zandalarian Hero Charm - // 24658 - Unstable Power - // Item - 19949: Zandalarian Hero Medallion - // 24661 - Restless Strength - [Script("spell_item_unstable_power", 24659)] - [Script("spell_item_restless_strength", 24662)] - class spell_item_zandalarian_charm : AuraScript - { - uint _spellId; - - public spell_item_zandalarian_charm(uint SpellId) - { - _spellId = SpellId; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_spellId); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo != null) - if (spellInfo.Id != m_scriptSpellId) - return true; - - return false; - } - - void HandleStackDrop(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().RemoveAuraFromStack(_spellId); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleStackDrop, 0, AuraType.Dummy)); - } - } - - [Script] - class spell_item_artifical_stamina : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - public override bool Load() - { - return GetOwner().IsPlayer(); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Item artifact = GetOwner().ToPlayer().GetItemByGuid(GetAura().GetCastItemGUID()); - if (artifact != null) - amount = (int)(GetEffectInfo(1).BasePoints * artifact.GetTotalPurchasedArtifactPowers() / 100); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModTotalStatPercentage)); - } - } - - [Script] - class spell_item_artifical_damage : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - public override bool Load() - { - return GetOwner().IsPlayer(); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Item artifact = GetOwner().ToPlayer().GetItemByGuid(GetAura().GetCastItemGUID()); - if (artifact != null) - amount = (int)(GetSpellInfo().GetEffect(1).BasePoints * artifact.GetTotalPurchasedArtifactPowers() / 100); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModDamagePercentDone)); - } - } - - [Script] // 28200 - Ascendance - class spell_item_talisman_of_ascendance : AuraScript - { - const uint SpellTalismanOfAscendance = 28200; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellTalismanOfAscendance); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - [Script] // 29602 - Jom Gabbar - class spell_item_jom_gabbar : AuraScript - { - const uint SpellJomGabbar = 29602; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellJomGabbar); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - [Script] // 45040 - Battle Trance - class spell_item_battle_trance : AuraScript - { - const uint SpellBattleTrance = 45040; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellBattleTrance); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - [Script] // 90900 - World-Queller Focus - class spell_item_world_queller_focus : AuraScript - { - const uint SpellWorldQuellerFocus = 90900; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellWorldQuellerFocus); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - // 118089 - Azure Water Strider - // 127271 - Crimson Water Strider - // 127272 - Orange Water Strider - // 127274 - Jade Water Strider - [Script] // 127278 - Golden Water Strider - class spell_item_water_strider : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(GetSpellInfo().GetEffect(1).TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.Mounted, AuraEffectHandleModes.Real)); - } - } - - // 144671 - Brutal Kinship - [Script] // 145738 - Brutal Kinship - class spell_item_brutal_kinship : AuraScript - { - const uint SpellBrutalKinship1 = 144671; - const uint SpellBrutalKinship2 = 145738; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellBrutalKinship1, SpellBrutalKinship2); - } - - void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); - } - } - - [Script] // 45051 - Mad Alchemist's Potion (34440) - class spell_item_mad_alchemists_potion : SpellScript - { - void SecondaryEffect() - { - List availableElixirs = new() - { - // Battle Elixirs - 33720, // Onslaught Elixir (28102) - 54452, // Adept's Elixir (28103) - 33726, // Elixir of Mastery (28104) - 28490, // Elixir of Major Strength (22824) - 28491, // Elixir of Healing Power (22825) - 28493, // Elixir of Major Frost Power (22827) - 54494, // Elixir of Major Agility (22831) - 28501, // Elixir of Major Firepower (22833) - 28503,// Elixir of Major Shadow Power (22835) - 38954, // Fel Strength Elixir (31679) - // Guardian Elixirs - 39625, // Elixir of Major Fortitude (32062) - 39626, // Earthen Elixir (32063) - 39627, // Elixir of Draenic Wisdom (32067) - 39628, // Elixir of Ironskin (32068) - 28502, // Elixir of Major Defense (22834) - 28514, // Elixir of Empowerment (22848) - // Other - 28489, // Elixir of Camouflage (22823) - 28496 // Elixir of the Searching Eye (22830) - }; - - Unit target = GetCaster(); - - if (target.GetPowerType() == PowerType.Mana) - availableElixirs.Add(28509); // Elixir of Major Mageblood (22840) - - uint chosenElixir = availableElixirs.SelectRandom(); - - bool useElixir = true; - - SpellGroup chosenSpellGroup = SpellGroup.None; - if (SpellMgr.IsSpellMemberOfSpellGroup(chosenElixir, SpellGroup.ElixirBattle)) - chosenSpellGroup = SpellGroup.ElixirBattle; - if (SpellMgr.IsSpellMemberOfSpellGroup(chosenElixir, SpellGroup.ElixirGuardian)) - chosenSpellGroup = SpellGroup.ElixirGuardian; - // If another spell of the same group is already active the elixir should not be cast - if (chosenSpellGroup != SpellGroup.None) - { - var auraMap = target.GetAppliedAuras(); - foreach (var (_, app) in auraMap) - { - uint spellId = app.GetBase().GetId(); - if (SpellMgr.IsSpellMemberOfSpellGroup(spellId, chosenSpellGroup) && spellId != chosenElixir) - { - useElixir = false; - break; - } - } - } - - if (useElixir) - target.CastSpell(target, chosenElixir, GetCastItem()); - } - - public override void Register() - { - AfterCast.Add(new(SecondaryEffect)); - } - } - - [Script] // 53750 - Crazy Alchemist's Potion (40077) - class spell_item_crazy_alchemists_potion : SpellScript - { - void SecondaryEffect() - { - List availableElixirs = new() - { - 43185, // Runic Healing Potion (33447) - 53750, // Crazy Alchemist's Potion (40077) - 53761, // Powerful Rejuvenation Potion (40087) - 53762, // Indestructible Potion (40093) - 53908, // Potion of Speed (40211) - 53909, // Potion of Wild Magic (40212) - 53910, // Mighty Arcane Protection Potion (40213) - 53911, // Mighty Fire Protection Potion (40214) - 53913, // Mighty Frost Protection Potion (40215) - 53914, // Mighty Nature Protection Potion (40216) - 53915 // Mighty Shadow Protection Potion (40217) - }; - - - Unit target = GetCaster(); - - if (!target.IsInCombat()) - availableElixirs.Add(53753); // Potion of Nightmares (40081) - if (target.GetPowerType() == PowerType.Mana) - availableElixirs.Add(43186); // Runic Mana Potion(33448) - - uint chosenElixir = availableElixirs.SelectRandom(); - - target.CastSpell(target, chosenElixir, GetCastItem()); - } - - public override void Register() - { - AfterCast.Add(new(SecondaryEffect)); - } - } - - [Script] // 21149 - Egg Nog - class spell_item_eggnog : SpellScript - { - const uint SpellEggNogReindeer = 21936; - const uint SpellEggNogSnowman = 21980; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellEggNogReindeer, SpellEggNogSnowman); - } - - void HandleScript(uint effIndex) - { - if (RandomHelper.randChance(40)) - GetCaster().CastSpell(GetHitUnit(), RandomHelper.randChance(50) ? SpellEggNogReindeer : SpellEggNogSnowman, GetCastItem()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 2, SpellEffectName.Inebriate)); - } - } - - // 208051 - Sephuz's Secret - // 234867 - Sephuz's Secret - [Script] // 236763 - Sephuz's Secret - class spell_item_sephuzs_secret : AuraScript - { - const uint SpellSephuzsSecretCooldown = 226262; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellSephuzsSecretCooldown); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - if (GetUnitOwner().HasAura(SpellSephuzsSecretCooldown)) - return false; - - if (eventInfo.GetHitMask().HasAnyFlag(ProcFlagsHit.Interrupt | ProcFlagsHit.Dispel)) - return true; - - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell == null) - return false; - - bool isCrowdControl = procSpell.GetSpellInfo().HasAura(AuraType.ModConfuse) - || procSpell.GetSpellInfo().HasAura(AuraType.ModFear) - || procSpell.GetSpellInfo().HasAura(AuraType.ModStun) - || procSpell.GetSpellInfo().HasAura(AuraType.ModPacify) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) - || procSpell.GetSpellInfo().HasAura(AuraType.ModSilence) - || procSpell.GetSpellInfo().HasAura(AuraType.ModPacifySilence) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2); - - if (!isCrowdControl) - return false; - - return true; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - PreventDefaultAction(); - - GetUnitOwner().CastSpell(GetUnitOwner(), SpellSephuzsSecretCooldown, TriggerCastFlags.FullMask); - GetUnitOwner().CastSpell(procInfo.GetProcTarget(), aurEff.GetSpellEffectInfo().TriggerSpell, new CastSpellExtraArgs(aurEff).SetTriggeringSpell(procInfo.GetProcSpell())); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 215266 - Fragile Echoes - class spell_item_amalgams_seventh_spine : AuraScript - { - const uint SpellFragileEchoesMonk = 225281; - const uint SpellFragileEchoesShaman = 225292; - const uint SpellFragileEchoesPriestDiscipline = 225294; - const uint SpellFragileEchoesPaladin = 225297; - const uint SpellFragileEchoesDruid = 225298; - const uint SpellFragileEchoesPriestHoly = 225366; - const uint SpellFragileEchoesEvoker = 429020; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFragileEchoesMonk, SpellFragileEchoesShaman, SpellFragileEchoesPriestDiscipline, SpellFragileEchoesPaladin, SpellFragileEchoesDruid, SpellFragileEchoesPriestHoly, SpellFragileEchoesEvoker); - } - - void UpdateSpecAura(bool apply) - { - Player target = GetUnitOwner().ToPlayer(); - if (target == null) - return; - - void updateAuraIfInCorrectSpec(ChrSpecialization spec, uint aura) - { - if (!apply || target.GetPrimarySpecialization() != spec) - target.RemoveAurasDueToSpell(aura); - else if (!target.HasAura(aura)) - target.CastSpell(target, aura, GetEffect(0)); - } - - switch (target.GetClass()) - { - case Class.Monk: - updateAuraIfInCorrectSpec(ChrSpecialization.MonkMistweaver, SpellFragileEchoesMonk); - break; - case Class.Shaman: - updateAuraIfInCorrectSpec(ChrSpecialization.ShamanRestoration, SpellFragileEchoesShaman); - break; - case Class.Priest: - updateAuraIfInCorrectSpec(ChrSpecialization.PriestDiscipline, SpellFragileEchoesPriestDiscipline); - updateAuraIfInCorrectSpec(ChrSpecialization.PriestHoly, SpellFragileEchoesPriestHoly); - break; - case Class.Paladin: - updateAuraIfInCorrectSpec(ChrSpecialization.PaladinHoly, SpellFragileEchoesPaladin); - break; - case Class.Druid: - updateAuraIfInCorrectSpec(ChrSpecialization.DruidRestoration, SpellFragileEchoesDruid); - break; - case Class.Evoker: - updateAuraIfInCorrectSpec(ChrSpecialization.EvokerPreservation, SpellFragileEchoesEvoker); - break; - default: - break; - } - } - - void HandleHeartbeat() - { - UpdateSpecAura(true); - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - UpdateSpecAura(false); - } - - public override void Register() - { - OnHeartbeat.Add(new(HandleHeartbeat)); - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 215267 - Fragile Echo - class spell_item_amalgams_seventh_spine_mana_restore : AuraScript - { - const uint SpellFragileEchoEnergize = 215270; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFragileEchoEnergize); - } - - void TriggerManaRestoration(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; - - Unit caster = GetCaster(); - if (caster == null) - return; - - AuraEffect trinketEffect = caster.GetAuraEffect(aurEff.GetSpellEffectInfo().TriggerSpell, 0); - if (trinketEffect != null) - caster.CastSpell(caster, SpellFragileEchoEnergize, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, trinketEffect.GetAmount())); - } - - public override void Register() - { - AfterEffectRemove.Add(new(TriggerManaRestoration, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 228445 - March of the Legion - class spell_item_set_march_of_the_legion : AuraScript - { - bool IsDemon(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().GetCreatureType() == CreatureType.Demon; - } - - public override void Register() - { - DoCheckEffectProc.Add(new(IsDemon, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 234113 - Arrogance (used by item 142171 - Seal of Darkshire Nobility) - class spell_item_seal_of_darkshire_nobility : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)) && ValidateSpellInfo(spellInfo.GetEffect(1).TriggerSpell); - } - - bool CheckCooldownAura(ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() != null && !eventInfo.GetProcTarget().HasAura(GetEffectInfo(1).TriggerSpell, GetTarget().GetGUID()); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckCooldownAura)); - } - } - - [Script] // 247625 - March of the Legion - class spell_item_lightblood_elixir : AuraScript - { - bool IsDemon(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().GetCreatureType() == CreatureType.Demon; - } - - public override void Register() - { - DoCheckEffectProc.Add(new(IsDemon, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 253287 - Highfather's Timekeeping - class spell_item_highfathers_machination : AuraScript - { - const uint SpellHighfathersTimekeepingHeal = 253288; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellHighfathersTimekeepingHeal); - } - - bool CheckHealth(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetDamageInfo() != null && GetTarget().HealthBelowPctDamaged(aurEff.GetAmount(), eventInfo.GetDamageInfo().GetDamage()); - } - - void Heal(AuraEffect aurEff, ProcEventInfo procInfo) - { - PreventDefaultAction(); - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(GetTarget(), SpellHighfathersTimekeepingHeal, aurEff); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckHealth, 0, AuraType.Dummy)); - OnEffectProc.Add(new(Heal, 0, AuraType.Dummy)); - } - } - - [Script] // 253323 - Shadow Strike - class spell_item_seeping_scourgewing : AuraScript - { - const uint SpellShadowStrikeAoeCheck = 255861; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellShadowStrikeAoeCheck); - } - - void TriggerIsolatedStrikeCheck(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellShadowStrikeAoeCheck, - new CastSpellExtraArgs(aurEff).SetTriggeringSpell(eventInfo.GetProcSpell())); - } - - public override void Register() - { - AfterEffectProc.Add(new(TriggerIsolatedStrikeCheck, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 255861 - Shadow Strike - class spell_item_seeping_scourgewing_aoe_check : SpellScript - { - const uint SpellIsolatedStrike = 255609; - - void TriggerAdditionalDamage() - { - if (GetUnitTargetCountForEffect(0) > 1) - return; - - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask) - { - OriginalCastId = GetSpell().m_originalCastId - }; - if (GetSpell().m_castItemLevel >= 0) - args.OriginalCastItemLevel = GetSpell().m_castItemLevel; - - GetCaster().CastSpell(GetHitUnit(), SpellIsolatedStrike, args); - } - - public override void Register() - { - AfterHit.Add(new(TriggerAdditionalDamage)); - } - } - - [Script] // 295175 - Spiteful Binding - class spell_item_grips_of_forsaken_sanity : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - bool CheckHealth(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetActor().GetHealthPct() >= (float)(GetEffectInfo(1).CalcValue()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckHealth, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 302385 - Resurrect Health - class spell_item_zanjir_scaleguard_greatcloak : AuraScript - { - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().HasEffect(SpellEffectName.Resurrect); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script("spell_item_shiver_venom_crossbow", 303559)]// 303358 Venomous Bolt - [Script("spell_item_shiver_venom_lance", 303562)]// 303361 Shivering Lance - class spell_item_shiver_venom_weapon_proc : AuraScript - { - const uint SpellShiverVenom = 301624; - - uint _additionalProcSpellId; - - public spell_item_shiver_venom_weapon_proc(uint additionalProcSpellId) - { - _additionalProcSpellId = additionalProcSpellId; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellShiverVenom, _additionalProcSpellId); - } - - void HandleAdditionalProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - if (procInfo.GetProcTarget().HasAura(SpellShiverVenom)) - procInfo.GetActor().CastSpell(procInfo.GetProcTarget(), _additionalProcSpellId, new CastSpellExtraArgs(aurEff) - .AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount()) - .SetTriggeringSpell(procInfo.GetProcSpell())); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleAdditionalProc, 1, AuraType.Dummy)); - } - } - - [Script] // 302774 - Arcane Tempest - class spell_item_phial_of_the_arcane_tempest_damage : SpellScript - { - void ModifyStacks() - { - if (GetUnitTargetCountForEffect(0) != 1 || GetTriggeringSpell() == null) - return; - - AuraEffect aurEff = GetCaster().GetAuraEffect(GetTriggeringSpell().Id, 0); - if (aurEff != null) - { - aurEff.GetBase().ModStackAmount(1, AuraRemoveMode.None, false); - aurEff.CalculatePeriodic(GetCaster(), false); - } - } - - public override void Register() - { - AfterCast.Add(new(ModifyStacks)); - } - } - - [Script] // 302769 - Arcane Tempest - class spell_item_phial_of_the_arcane_tempest_periodic : AuraScript - { - void CalculatePeriod(AuraEffect aurEff, ref bool isPeriodic, ref int period) - { - period -= (GetStackAmount() - 1) * 300; - } - - public override void Register() - { - DoEffectCalcPeriodic.Add(new(CalculatePeriod, 0, AuraType.PeriodicTriggerSpell)); - } - } - - // 410530 - Mettle - [Script] // 410964 - Mettle - class spell_item_infurious_crafted_gear_mettle : AuraScript - { - uint SpellMettleCooldown = 410532; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellMettleCooldown); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - if (GetTarget().HasAura(SpellMettleCooldown)) - return false; - - if (eventInfo.GetHitMask().HasAnyFlag(ProcFlagsHit.Interrupt | ProcFlagsHit.Dispel)) - return true; - - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell == null) - return false; - - bool isCrowdControl = procSpell.GetSpellInfo().HasAura(AuraType.ModConfuse) - || procSpell.GetSpellInfo().HasAura(AuraType.ModFear) - || procSpell.GetSpellInfo().HasAura(AuraType.ModStun) - || procSpell.GetSpellInfo().HasAura(AuraType.ModPacify) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) - || procSpell.GetSpellInfo().HasAura(AuraType.ModSilence) - || procSpell.GetSpellInfo().HasAura(AuraType.ModPacifySilence) - || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2); - - if (!isCrowdControl) - return false; - - return eventInfo.GetActionTarget().HasAura(aura => aura.GetCastId() == procSpell.m_castId); - } - - void TriggerCooldown(ProcEventInfo eventInfo) - { - GetTarget().CastSpell(GetTarget(), SpellMettleCooldown, true); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - AfterProc.Add(new(TriggerCooldown)); + return false; // do not delete re-added event in EventProcessor::Update } } } + +[Script] // 51010 - Dire Brew +class spell_item_dire_brew : AuraScript +{ + void AfterApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + + uint model = 0; + Gender gender = target.GetGender(); + var chrClass = CliDB.ChrClassesStorage.LookupByKey(target.GetClass()); + if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Plate)) != 0) + model = gender == Gender.Male ? MiscConst.ModelClassPlateMale : MiscConst.ModelClassPlateFemale; + else if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Mail)) != 0) + model = gender == Gender.Male ? MiscConst.ModelClassMailMale : MiscConst.ModelClassMailFemale; + else if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Leather)) != 0) + model = gender == Gender.Male ? MiscConst.ModelClassLeatherMale : MiscConst.ModelClassLeatherFemale; + else if ((chrClass.ArmorTypeMask & (1 << (int)ItemSubClassArmor.Cloth)) != 0) + model = gender == Gender.Male ? MiscConst.ModelClassClothMale : MiscConst.ModelClassClothFemale; + + if (model != 0) + target.SetDisplayId(model); + } + + public override void Register() + { + AfterEffectApply.Add(new(AfterApply, 0, AuraType.Transform, AuraEffectHandleModes.Real)); + } +} + +[Script] // 59915 - Discerning Eye of the Beast Dummy +class spell_item_discerning_eye_beast_dummy : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DiscerningEyeBeast); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + eventInfo.GetActor().CastSpell(null, SpellIds.DiscerningEyeBeast, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 71610, 71641 - Echoes of Light (Althor's Abacus) +class spell_item_echoes_of_light : SpellScript +{ + void FilterTargets(List targets) + { + if (targets.Count < 2) + return; + + targets.Sort(new HealthPctOrderPred()); + + WorldObject target = targets.First(); + targets.Clear(); + targets.Add(target); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +[Script] // 30427 - Extract Gas (23821: Zapthrottle Mote Extractor) +class spell_item_extract_gas : AuraScript +{ + void PeriodicTick(AuraEffect aurEff) + { + PreventDefaultAction(); + + // move loot to player inventory and despawn target + if (GetCaster() != null && GetCaster().IsPlayer() && GetTarget().IsUnit() && + GetTarget().ToCreature().GetCreatureTemplate().CreatureType == CreatureType.GasCloud) + { + Player player = GetCaster().ToPlayer(); + Creature creature = GetTarget().ToCreature(); + CreatureDifficulty creatureDifficulty = creature.GetCreatureDifficulty(); + // missing lootid has been reported on startup - just return + if (creatureDifficulty.SkinLootID == 0) + return; + + player.AutoStoreLoot(creatureDifficulty.SkinLootID, LootStorage.Skinning, ItemContext.None, true); + creature.DespawnOrUnsummon(); + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(PeriodicTick, 0, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 7434 - Fate Rune of Unsurpassed Vigor +class spell_item_fate_rune_of_unsurpassed_vigor : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UnsurpassedVigor); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.UnsurpassedVigor, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +/* 57301 - Great Feast + 57426 - Fish Feast + 58465 - Gigantic Feast + 58474 - Small Feast + 66476 - Bountiful Feast */ +[Script("spell_item_great_feast", MiscConst.TextGreatFeast)] +[Script("spell_item_fish_feast", MiscConst.TextFishFeast)] +[Script("spell_item_gigantic_feast", MiscConst.TextGiganticFeast)] +[Script("spell_item_small_feast", MiscConst.TextSmallFeast)] +[Script("spell_item_bountiful_feast", MiscConst.TextBountifulFeast)] +class spell_item_feast(uint text) : SpellScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return CliDB.BroadcastTextStorage.ContainsKey(text); + } + + void HandleScript(uint effIndex) + { + Unit caster = GetCaster(); + caster.TextEmote(text, caster, false); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +// http://www.wowhead.com/item=47499 Flask of the North +[Script] // 67019 Flask of the North +class spell_item_flask_of_the_north : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlaskOfTheNorthSp, SpellIds.FlaskOfTheNorthAp, SpellIds.FlaskOfTheNorthStr); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + List possibleSpells = new(); + switch (caster.GetClass()) + { + case Class.Warlock: + case Class.Mage: + case Class.Priest: + possibleSpells.Add(SpellIds.FlaskOfTheNorthSp); + break; + case Class.DeathKnight: + case Class.Warrior: + possibleSpells.Add(SpellIds.FlaskOfTheNorthStr); + break; + case Class.Rogue: + case Class.Hunter: + possibleSpells.Add(SpellIds.FlaskOfTheNorthAp); + break; + case Class.Druid: + case Class.Paladin: + possibleSpells.Add(SpellIds.FlaskOfTheNorthSp); + possibleSpells.Add(SpellIds.FlaskOfTheNorthStr); + break; + case Class.Shaman: + possibleSpells.Add(SpellIds.FlaskOfTheNorthSp); + possibleSpells.Add(SpellIds.FlaskOfTheNorthAp); + break; + } + + if (possibleSpells.Empty()) + { + Log.outWarn(LogFilter.Spells, $"Missing spells for class {caster.GetClass()} in script spell_item_flask_of_the_north"); + return; + } + + caster.CastSpell(caster, possibleSpells.SelectRandom(), true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// 39372 - Frozen Shadoweave +[Script] // Frozen Shadoweave set 3p bonus +class spell_item_frozen_shadoweave : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Shadowmend); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + Unit caster = eventInfo.GetActor(); + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount())); + caster.CastSpell(null, SpellIds.Shadowmend, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// http://www.wowhead.com/item=10645 Gnomish Death Ray +[Script] // 13280 Gnomish Death Ray +class spell_item_gnomish_death_ray : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GnomishDeathRaySelf, SpellIds.GnomishDeathRayTarget); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target != null) + { + if (RandomHelper.URand(0, 99) < 15) + caster.CastSpell(caster, SpellIds.GnomishDeathRaySelf, true); // failure + else + caster.CastSpell(target, SpellIds.GnomishDeathRayTarget, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// Item 10721: Gnomish Harm Prevention Belt +[Script] // 13234 - Harm Prevention Belt +class spell_item_harm_prevention_belt : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ForcefieldCollapse); + } + + void HandleProc(ProcEventInfo eventInfo) + { + GetTarget().CastSpell(null, SpellIds.ForcefieldCollapse, true); + } + + public override void Register() + { + OnProc.Add(new(HandleProc)); + } +} + +// Item - 49982: Heartpierce +// 71880 - Item - Icecrown 25 Normal Dagger Proc + +// Item - 50641: Heartpierce (Heroic) +// 71892 - Item - Icecrown 25 Heroic Dagger Proc +[Script("spell_item_heartpierce", SpellIds.InvigorationEnergy, SpellIds.InvigorationMana, SpellIds.InvigorationRage, SpellIds.InvigorationRp)] +[Script("spell_item_heartpierce_hero", SpellIds.InvigorationEnergyHero, SpellIds.InvigorationManaHero, SpellIds.InvigorationRageHero, SpellIds.InvigorationRpHero)] +class spell_item_heartpierce(uint Energy, uint Mana, uint Rage, uint RunicPower) : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(Energy, Mana, Rage, RunicPower); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + + uint spellId; + switch (caster.GetPowerType()) + { + case PowerType.Mana: + spellId = Mana; + break; + case PowerType.Energy: + spellId = Energy; + break; + case PowerType.Rage: + spellId = Rage; + break; + // Death Knights can't use daggers, but oh well + case PowerType.RunicPower: + spellId = RunicPower; + break; + default: + return; + } + + caster.CastSpell(null, spellId, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 23645 - Hourglass Sand +class spell_item_hourglass_sand : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BroodAfflictionBronze); + } + + void HandleDummy(uint effIndex) + { + GetCaster().RemoveAurasDueToSpell(SpellIds.BroodAfflictionBronze); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 40971 - Bonus Healing (Crystal Spire of Karabor) +class spell_item_crystal_spire_of_karabor : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 0)); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + int pct = GetSpellInfo().GetEffect(0).CalcValue(); + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo != null) + { + Unit healTarget = healInfo.GetTarget(); + if (healTarget != null && healTarget.GetHealth() - healInfo.GetEffectiveHeal() <= healTarget.CountPctFromMaxHealth(pct)) + return true; + } + + return false; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +// http://www.wowhead.com/item=27388 Mr. Pinchy +[Script] // 33060 Make a Wish +class spell_item_make_a_wish : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MrPinchysBlessing, SpellIds.SummonMightyMrPinchy, SpellIds.SummonFuriousMrPinchy, SpellIds.TinyMagicalCrawdad, SpellIds.MrPinchysGift); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + uint spellId = SpellIds.MrPinchysGift; + switch (RandomHelper.URand(1, 5)) + { + case 1: + spellId = SpellIds.MrPinchysBlessing; + break; + case 2: + spellId = SpellIds.SummonMightyMrPinchy; + break; + case 3: + spellId = SpellIds.SummonFuriousMrPinchy; + break; + case 4: + spellId = SpellIds.TinyMagicalCrawdad; + break; + } + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// Item - 27920: Mark of Conquest +// Item - 27921: Mark of Conquest +[Script] // 33510 - Health Restore +class spell_item_mark_of_conquest : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MarkOfConquestEnergize); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + if (eventInfo.GetTypeMask() & new ProcFlagsInit(ProcFlags.DealRangedAttack | ProcFlags.DealRangedAbility)) + { + // in that case, do not cast heal spell + PreventDefaultAction(); + // but mana instead + eventInfo.GetActor().CastSpell(null, SpellIds.MarkOfConquestEnergize, aurEff); + } + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 26465 - Mercurial Shield +class spell_item_mercurial_shield : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MercurialShield); + } + + void HandleScript(uint effIndex) + { + GetHitUnit().RemoveAuraFromStack(SpellIds.MercurialShield); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +// http://www.wowhead.com/item=32686 Mingo's Fortune Giblets +[Script] // 40802 Mingo's Fortune Generator +class spell_item_mingos_fortune_generator : SpellScript +{ + uint[] CreateFortuneSpells = + [ + SpellIds.CreateFortune1, SpellIds.CreateFortune2, SpellIds.CreateFortune3, SpellIds.CreateFortune4, SpellIds.CreateFortune5, + SpellIds.CreateFortune6, SpellIds.CreateFortune7, SpellIds.CreateFortune8, SpellIds.CreateFortune9, SpellIds.CreateFortune10, + SpellIds.CreateFortune11, SpellIds.CreateFortune12, SpellIds.CreateFortune13, SpellIds.CreateFortune14, SpellIds.CreateFortune15, + SpellIds.CreateFortune16, SpellIds.CreateFortune17, SpellIds.CreateFortune18, SpellIds.CreateFortune19, SpellIds.CreateFortune20 + ]; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(CreateFortuneSpells); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), CreateFortuneSpells.SelectRandom(), true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 71875, 71877 - Item - Black Bruise: Necrotic Touch Proc +class spell_item_necrotic_touch : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ItemNecroticTouchProc); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().IsAlive(); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount())); + GetTarget().CastSpell(null, SpellIds.ItemNecroticTouchProc, args); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// http://www.wowhead.com/item=10720 Gnomish Net-o-Matic Projector +[Script] // 13120 Net-o-Matic +class spell_item_net_o_matic : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NetOMaticTRIGGERED1, SpellIds.NetOMaticTRIGGERED2, SpellIds.NetOMaticTRIGGERED3); + } + + void HandleDummy(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) + { + uint spellId = SpellIds.NetOMaticTRIGGERED3; + uint roll = RandomHelper.URand(0, 99); + if (roll < 2) // 2% for 30 sec self root (off-like chance unknown) + spellId = SpellIds.NetOMaticTRIGGERED1; + else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown) + spellId = SpellIds.NetOMaticTRIGGERED2; + + GetCaster().CastSpell(target, spellId, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// http://www.wowhead.com/item=8529 Noggenfogger Elixir +[Script] // 16589 Noggenfogger Elixir +class spell_item_noggenfogger_elixir : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NoggenfoggerElixirTRIGGERED1, SpellIds.NoggenfoggerElixirTRIGGERED2, SpellIds.NoggenfoggerElixirTRIGGERED3); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + uint spellId = SpellIds.NoggenfoggerElixirTRIGGERED3; + switch (RandomHelper.URand(1, 3)) + { + case 1: + spellId = SpellIds.NoggenfoggerElixirTRIGGERED1; + break; + case 2: + spellId = SpellIds.NoggenfoggerElixirTRIGGERED2; + break; + } + + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 29601 - Enlightenment (Pendant of the Violet Eye) +class spell_item_pendant_of_the_violet_eye : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) + { + Spell spell = eventInfo.GetProcSpell(); + if (spell != null && spell.GetPowerTypeCostAmount(PowerType.Mana) > 0) + return true; + + return false; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] // 26467 - Persistent Shield +class spell_item_persistent_shield : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PersistentShieldTriggered); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetHealInfo() != null && eventInfo.GetHealInfo().GetHeal() != 0; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + int bp0 = (int)MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), 15); + + // Scarab Brooch does not replace stronger shields + AuraEffect shield = target.GetAuraEffect(SpellIds.PersistentShieldTriggered, 0, caster.GetGUID()); + if (shield != null && shield.GetAmount() > bp0) + return; + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, bp0); + caster.CastSpell(target, SpellIds.PersistentShieldTriggered, args); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +// 37381 - Pet Healing +// Hunter T5 2P Bonus +[Script] // Warlock T5 2P Bonus +class spell_item_pet_healing : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HealthLink); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount())); + eventInfo.GetActor().CastSpell(null, SpellIds.HealthLink, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 17512 - Piccolo of the Flaming Fire +class spell_item_piccolo_of_the_flaming_fire : SpellScript +{ + void HandleScript(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + Player target = GetHitPlayer(); + if (target != null) + target.HandleEmoteCommand(Emote.StateDance); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 45043 - Power Circle (Shifting Naaru Sliver) +class spell_item_power_circle : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LimitlessPower); + } + + bool CheckCaster(Unit target) + { + return target.GetGUID() == GetCasterGUID(); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().CastSpell(null, SpellIds.LimitlessPower, true); + Aura buff = GetTarget().GetAura(SpellIds.LimitlessPower); + if (buff != null) + buff.SetDuration(GetDuration()); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.LimitlessPower); + } + + public override void Register() + { + DoCheckAreaTarget.Add(new(CheckCaster)); + + AfterEffectApply.Add(new(OnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +// http://www.wowhead.com/item=6657 Savory Deviate Delight +[Script] // 8213 Savory Deviate Delight +class spell_item_savory_deviate_delight : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlipOutMale, SpellIds.FlipOutFemale, SpellIds.YaaarrrrMale, SpellIds.YaaarrrrFemale); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + uint spellId = 0; + switch (RandomHelper.URand(1, 2)) + { + // Flip Out - ninja + case 1: spellId = (caster.GetNativeGender() == Gender.Male ? SpellIds.FlipOutMale : SpellIds.FlipOutFemale); break; + // Yaaarrrr - pirate + case 2: spellId = (caster.GetNativeGender() == Gender.Male ? SpellIds.YaaarrrrMale : SpellIds.YaaarrrrFemale); break; + } + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// 48129 - Scroll of Recall +// 60320 - Scroll of Recall Ii +[Script] // 60321 - Scroll of Recall Iii +class spell_item_scroll_of_recall : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + Unit caster = GetCaster(); + byte maxSafeLevel = 0; + switch (GetSpellInfo().Id) + { + case SpellIds.ScrollOfRecallI: // Scroll of Recall + maxSafeLevel = 40; + break; + case SpellIds.ScrollOfRecallIi: // Scroll of Recall Ii + maxSafeLevel = 70; + break; + case SpellIds.ScrollOfRecallIii: // Scroll of Recal Iii + maxSafeLevel = 80; + break; + default: + break; + } + + if (caster.GetLevel() > maxSafeLevel) + { + caster.CastSpell(caster, SpellIds.Lost, true); + + // Alliance from 60323 to 60330 - Horde from 60328 to 60335 + uint spellId = SpellIds.ScrollOfRecallFailAlliance1; + if (GetCaster().ToPlayer().GetTeam() == Team.Horde) + spellId = SpellIds.ScrollOfRecallFailHorde1; + + GetCaster().CastSpell(GetCaster(), spellId + RandomHelper.URand(0, 7), true); + + PreventHitDefaultEffect(effIndex); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); + } +} + +[Script] // 23442 - Dimensional Ripper - Everlook +class spell_item_dimensional_ripper_everlook : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TransporterMalfunctionFire, SpellIds.EvilTwin); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + int r = RandomHelper.IRand(0, 119); + if (r <= 70) // 7/12 success + return; + + Unit caster = GetCaster(); + + if (r < 100) // 4/12 evil twin + caster.CastSpell(caster, SpellIds.EvilTwin, true); + else // 1/12 fire + caster.CastSpell(caster, SpellIds.TransporterMalfunctionFire, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); + } +} + +[Script] // 36941 - Ultrasafe Transporter: Toshley's Station +class spell_item_ultrasafe_transporter : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TransporterMalfunctionSmaller, SpellIds.TransporterMalfunctionBigger, SpellIds.SoulSplitEvil, SpellIds.SoulSplitGood, SpellIds.TransformHorde, SpellIds.TransformAlliance, SpellIds.TransporterMalfunctionChicken, SpellIds.EvilTwin); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + if (!RandomHelper.randChance(50)) // 50% success + return; + + Unit caster = GetCaster(); + + uint spellId = 0; + switch (RandomHelper.URand(0, 6)) + { + case 0: + spellId = SpellIds.TransporterMalfunctionSmaller; + break; + case 1: + spellId = SpellIds.TransporterMalfunctionBigger; + break; + case 2: + spellId = SpellIds.SoulSplitEvil; + break; + case 3: + spellId = SpellIds.SoulSplitGood; + break; + case 4: + if (caster.ToPlayer().GetTeam() == Team.Alliance) + spellId = SpellIds.TransformHorde; + else + spellId = SpellIds.TransformAlliance; + break; + case 5: + spellId = SpellIds.TransporterMalfunctionChicken; + break; + case 6: + spellId = SpellIds.EvilTwin; + break; + default: + break; + } + + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); + } +} + +[Script] // 36890 - Dimensional Ripper - Area 52 +class spell_item_dimensional_ripper_area52 : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TransporterMalfunctionBigger, SpellIds.SoulSplitEvil, SpellIds.SoulSplitGood, SpellIds.TransformHorde, SpellIds.TransformAlliance); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + if (!RandomHelper.randChance(50)) // 50% success + return; + + Unit caster = GetCaster(); + + uint spellId = 0; + switch (RandomHelper.URand(0, 3)) + { + case 0: + spellId = SpellIds.TransporterMalfunctionBigger; + break; + case 1: + spellId = SpellIds.SoulSplitEvil; + break; + case 2: + spellId = SpellIds.SoulSplitGood; + break; + case 3: + if (caster.ToPlayer().GetTeam() == Team.Alliance) + spellId = SpellIds.TransformHorde; + else + spellId = SpellIds.TransformAlliance; + break; + default: + break; + } + + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TeleportUnits)); + } +} + +[Script] // 71169 - Shadow's Fate (Shadowmourne questline) +class spell_item_unsated_craving : AuraScript +{ + bool CheckProc(ProcEventInfo procInfo) + { + Unit caster = procInfo.GetActor(); + if (caster == null || caster.GetTypeId() != TypeId.Player) + return false; + + Unit target = procInfo.GetActionTarget(); + if (target == null || target.GetTypeId() != TypeId.Unit || target.IsCritter() || (target.GetEntry() != MiscConst.NpcSindragosa && target.IsSummon())) + return false; + + return true; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] +class spell_item_shadows_fate : AuraScript +{ + void HandleProc(ProcEventInfo procInfo) + { + PreventDefaultAction(); + + Unit caster = procInfo.GetActor(); + Unit target = GetCaster(); + if (caster == null || target == null) + return; + + caster.CastSpell(target, SpellIds.SoulFeast, TriggerCastFlags.FullMask); + } + + public override void Register() + { + OnProc.Add(new(HandleProc)); + } +} + +[Script] // 71903 - Item - Shadowmourne Legendary +class spell_item_shadowmourne : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowmourneChaosBaneDamage, SpellIds.ShadowmourneSoulFragment, SpellIds.ShadowmourneChaosBaneBuff); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (GetTarget().HasAura(SpellIds.ShadowmourneChaosBaneBuff)) // cant collect shards while under effect of Chaos Bane buff + return false; + return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().IsAlive(); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.ShadowmourneSoulFragment, aurEff); + + // this can't be handled in AuraScript of SoulFragments because we need to know victim + Aura soulFragments = GetTarget().GetAura(SpellIds.ShadowmourneSoulFragment); + if (soulFragments != null) + { + if (soulFragments.GetStackAmount() >= 10) + { + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.ShadowmourneChaosBaneDamage, aurEff); + soulFragments.Remove(); + } + } + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.ShadowmourneSoulFragment); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 71905 - Soul Fragment +class spell_item_shadowmourne_soul_fragment : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowmourneVisualLow, SpellIds.ShadowmourneVisualHigh, SpellIds.ShadowmourneChaosBaneBuff); + } + + void OnStackChange(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + switch (GetStackAmount()) + { + case 1: + target.CastSpell(target, SpellIds.ShadowmourneVisualLow, true); + break; + case 6: + target.RemoveAurasDueToSpell(SpellIds.ShadowmourneVisualLow); + target.CastSpell(target, SpellIds.ShadowmourneVisualHigh, true); + break; + case 10: + target.RemoveAurasDueToSpell(SpellIds.ShadowmourneVisualHigh); + target.CastSpell(target, SpellIds.ShadowmourneChaosBaneBuff, true); + break; + default: + break; + } + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveAurasDueToSpell(SpellIds.ShadowmourneVisualLow); + target.RemoveAurasDueToSpell(SpellIds.ShadowmourneVisualHigh); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnStackChange, 0, AuraType.ModStat, AuraEffectHandleModes.Real | AuraEffectHandleModes.Reapply)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.ModStat, AuraEffectHandleModes.Real)); + } +} + +// http://www.wowhead.com/item=7734 Six Demon Bag +[Script] // 14537 Six Demon Bag +class spell_item_six_demon_bag : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Frostbolt, SpellIds.Polymorph, SpellIds.SummonFelhoundMinion, SpellIds.Fireball, SpellIds.ChainLightning, SpellIds.EnvelopingWinds); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target != null) + { + uint spellId = 0; + uint rand = RandomHelper.URand(0, 99); + if (rand < 25) // Fireball (25% chance) + spellId = SpellIds.Fireball; + else if (rand < 50) // Frostball (25% chance) + spellId = SpellIds.Frostbolt; + else if (rand < 70) // Chain Lighting (20% chance) + spellId = SpellIds.ChainLightning; + else if (rand < 80) // Polymorph (10% chance) + { + spellId = SpellIds.Polymorph; + if (RandomHelper.URand(0, 100) <= 30) // 30% chance to self-cast + target = caster; + } + else if (rand < 95) // Enveloping Winds (15% chance) + spellId = SpellIds.EnvelopingWinds; + else // Summon Felhund minion (5% chance) + { + spellId = SpellIds.SummonFelhoundMinion; + target = caster; + } + + caster.CastSpell(target, spellId, GetCastItem()); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 59906 - Swift Hand of Justice Dummy +class spell_item_swift_hand_justice_dummy : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SwiftHandOfJusticeHeal); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)caster.CountPctFromMaxHealth(aurEff.GetAmount())); + caster.CastSpell(null, SpellIds.SwiftHandOfJusticeHeal, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 28862 - The Eye of Diminution +class spell_item_the_eye_of_diminution : AuraScript +{ + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + int diff = (int)GetUnitOwner().GetLevel() - 60; + if (diff > 0) + amount += diff; + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModThreat)); + } +} + +// http://www.wowhead.com/item=44012 Underbelly Elixir +[Script] // 59640 Underbelly Elixir +class spell_item_underbelly_elixir : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UnderbellyElixirTriggered1, SpellIds.UnderbellyElixirTriggered2, SpellIds.UnderbellyElixirTriggered3); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + uint spellId = SpellIds.UnderbellyElixirTriggered3; + switch (RandomHelper.URand(1, 3)) + { + case 1: + spellId = SpellIds.UnderbellyElixirTriggered1; + break; + case 2: + spellId = SpellIds.UnderbellyElixirTriggered2; + break; + } + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 126755 - Wormhole: Pandaria +class spell_item_wormhole_pandaria : SpellScript +{ + uint[] WormholeTargetLocations = + { + SpellIds.WormholePandariaIsleOfReckoning, + SpellIds.WormholePandariaKunlaiUnderwater, + SpellIds.WormholePandariaSraVess, + SpellIds.WormholePandariaRikkitunVillage, + SpellIds.WormholePandariaZanvessTree, + SpellIds.WormholePandariaAnglersWharf, + SpellIds.WormholePandariaCraneStatue, + SpellIds.WormholePandariaEmperorsOmen, + SpellIds.WormholePandariaWhitepetalLake + }; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(WormholeTargetLocations); + } + + void HandleTeleport(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + uint spellId = WormholeTargetLocations.SelectRandom(); + GetCaster().CastSpell(GetHitUnit(), spellId, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleTeleport, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 47776 - Roll 'dem Bones +class spell_item_worn_troll_dice : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (!CliDB.BroadcastTextStorage.ContainsKey(MiscConst.TextWornTrollDice)) + return false; + return true; + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + GetCaster().TextEmote(MiscConst.TextWornTrollDice, GetHitUnit()); + + uint minimum = 1; + uint maximum = 6; + + // roll twice + GetCaster().ToPlayer().DoRandomRoll(minimum, maximum); + GetCaster().ToPlayer().DoRandomRoll(minimum, maximum); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_item_red_rider_air_rifle : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AirRifleHoldVisual, SpellIds.AirRifleShoot, SpellIds.AirRifleShootSelf); + } + + void HandleScript(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target != null) + { + caster.CastSpell(caster, SpellIds.AirRifleHoldVisual, true); + // needed because this spell shares Gcd with its triggered spells (which must not be cast with triggered flag) + Player player = caster.ToPlayer(); + if (player != null) + player.GetSpellHistory().CancelGlobalCooldown(GetSpellInfo()); + if (RandomHelper.URand(0, 4) != 0) + caster.CastSpell(target, SpellIds.AirRifleShoot, false); + else + caster.CastSpell(caster, SpellIds.AirRifleShootSelf, false); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_item_book_of_glyph_mastery : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + SpellCastResult CheckRequirement() + { + if (SkillDiscovery.HasDiscoveredAllSpells(GetSpellInfo().Id, GetCaster().ToPlayer())) + { + SetCustomCastResultMessage(SpellCustomErrors.LearnedEverything); + return SpellCastResult.CustomError; + } + + return SpellCastResult.SpellCastOk; + } + + void HandleScript(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + uint spellId = GetSpellInfo().Id; + + // learn random explicit discovery recipe (if any) + uint discoveredSpellId = SkillDiscovery.GetExplicitDiscoverySpell(spellId, caster); + if (discoveredSpellId != 0) + caster.LearnSpell(discoveredSpellId, false); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckRequirement)); + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] +class spell_item_gift_of_the_harvester : SpellScript +{ + SpellCastResult CheckRequirement() + { + List ghouls = GetCaster().GetAllMinionsByEntry(MiscConst.NpcGhoul); + if (ghouls.Count >= MiscConst.MaxGhouls) + { + SetCustomCastResultMessage(SpellCustomErrors.TooManyGhouls); + return SpellCastResult.CustomError; + } + + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckRequirement)); + } +} + +[Script] +class spell_item_map_of_the_geyser_fields : SpellScript +{ + SpellCastResult CheckSinkholes() + { + Unit caster = GetCaster(); + if (caster.FindNearestCreature(MiscConst.NpcSouthSinkhole, 30.0f, true) != null || + caster.FindNearestCreature(MiscConst.NpcNortheastSinkhole, 30.0f, true) != null || + caster.FindNearestCreature(MiscConst.NpcNorthwestSinkhole, 30.0f, true) != null) + return SpellCastResult.SpellCastOk; + + SetCustomCastResultMessage(SpellCustomErrors.MustBeCloseToSinkhole); + return SpellCastResult.CustomError; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckSinkholes)); + } +} + +[Script] +class spell_item_vanquished_clutches : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Crusher, SpellIds.Constrictor, SpellIds.Corruptor); + } + + void HandleDummy(uint effIndex) + { + uint spellId = RandomHelper.RAND(SpellIds.Crusher, SpellIds.Constrictor, SpellIds.Corruptor); + Unit caster = GetCaster(); + caster.CastSpell(caster, spellId, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_ashbringer : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void OnDummyEffect(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + + Player player = GetCaster().ToPlayer(); + uint sound_id = RandomHelper.RAND(MiscConst.SoundAshbringer1, MiscConst.SoundAshbringer2, MiscConst.SoundAshbringer3, MiscConst.SoundAshbringer4, MiscConst.SoundAshbringer5, MiscConst.SoundAshbringer6, + MiscConst.SoundAshbringer7, MiscConst.SoundAshbringer8, MiscConst.SoundAshbringer9, MiscConst.SoundAshbringer10, MiscConst.SoundAshbringer11, MiscConst.SoundAshbringer12); + + // Ashbringers effect (spellId 28441) retriggers every 5 seconds, with a chance of making it say one of the above 12 sounds + if (RandomHelper.URand(0, 60) < 1) + player.PlayDirectSound(sound_id, player); + } + + public override void Register() + { + OnEffectHit.Add(new(OnDummyEffect, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 58886 - Food +class spell_magic_eater_food : AuraScript +{ + void HandleTriggerSpell(AuraEffect aurEff) + { + PreventDefaultAction(); + Unit target = GetTarget(); + switch (RandomHelper.URand(0, 5)) + { + case 0: + target.CastSpell(target, SpellIds.WildMagic, true); + break; + case 1: + target.CastSpell(target, SpellIds.WellFed1, true); + break; + case 2: + target.CastSpell(target, SpellIds.WellFed2, true); + break; + case 3: + target.CastSpell(target, SpellIds.WellFed3, true); + break; + case 4: + target.CastSpell(target, SpellIds.WellFed4, true); + break; + case 5: + target.CastSpell(target, SpellIds.WellFed5, true); + break; + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleTriggerSpell, 1, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] +class spell_item_purify_helboar_meat : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SummonPurifiedHelboarMeat, SpellIds.SummonToxicHelboarMeat); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + caster.CastSpell(caster, RandomHelper.randChance(50) ? SpellIds.SummonPurifiedHelboarMeat : SpellIds.SummonToxicHelboarMeat, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_nigh_invulnerability : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NighInvulnerability, SpellIds.CompleteVulnerability); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Item castItem = GetCastItem(); + if (castItem != null) + { + if (RandomHelper.randChance(86)) // Nigh-Invulnerability - success + caster.CastSpell(caster, SpellIds.NighInvulnerability, castItem); + else // Complete Vulnerability - backfire in 14% casts + caster.CastSpell(caster, SpellIds.CompleteVulnerability, castItem); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_poultryizer : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PoultryizerSuccess, SpellIds.PoultryizerBackfire); + } + + void HandleDummy(uint effIndex) + { + if (GetCastItem() != null && GetHitUnit() != null) + GetCaster().CastSpell(GetHitUnit(), RandomHelper.randChance(80) ? SpellIds.PoultryizerSuccess : SpellIds.PoultryizerBackfire, GetCastItem()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_socrethars_stone : SpellScript +{ + public override bool Load() + { + return (GetCaster().GetAreaId() == 3900 || GetCaster().GetAreaId() == 3742); + } + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SocretharToSeat, SpellIds.SocretharFromSeat); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + switch (caster.GetAreaId()) + { + case 3900: + caster.CastSpell(caster, SpellIds.SocretharToSeat, true); + break; + case 3742: + caster.CastSpell(caster, SpellIds.SocretharFromSeat, true); + break; + default: + return; + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_demon_broiled_surprise : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CreateDemonBroiledSurprise) && + Global.ObjectMgr.GetCreatureTemplate(MiscConst.NpcAbyssalFlamebringer) != null && + Global.ObjectMgr.GetQuestTemplate(MiscConst.QuestSuperHotStew) != null; + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleDummy(uint effIndex) + { + Unit player = GetCaster(); + player.CastSpell(player, SpellIds.CreateDemonBroiledSurprise, false); + } + + SpellCastResult CheckRequirement() + { + Player player = GetCaster().ToPlayer(); + if (player.GetQuestStatus(MiscConst.QuestSuperHotStew) != QuestStatus.Incomplete) + return SpellCastResult.CantDoThatRightNow; + + Creature creature = player.FindNearestCreature(MiscConst.NpcAbyssalFlamebringer, 10, false); + if (creature != null && creature.IsDead()) + return SpellCastResult.SpellCastOk; + return SpellCastResult.NotHere; + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); + OnCheckCast.Add(new(CheckRequirement)); + } +} + +[Script] +class spell_item_complete_raptor_capture : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RaptorCaptureCredit); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + if (GetHitCreature() != null) + { + GetHitCreature().DespawnOrUnsummon(); + + //cast spell Raptor Capture Credit + caster.CastSpell(caster, SpellIds.RaptorCaptureCredit, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_impale_leviroth : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (Global.ObjectMgr.GetCreatureTemplate(MiscConst.NpcLeviroth) == null) + return false; + return true; + } + + void HandleDummy(uint effIndex) + { + Creature target = GetHitCreature(); + if (target != null) + if (target.GetEntry() == MiscConst.NpcLeviroth && !target.HealthBelowPct(95)) + { + target.CastSpell(target, SpellIds.LevirothSelfImpale, true); + target.ResetPlayerDamageReq(); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 23725 - Gift of Life +class spell_item_lifegiving_gem : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GiftOfLife1, SpellIds.GiftOfLife2); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + caster.CastSpell(caster, SpellIds.GiftOfLife1, true); + caster.CastSpell(caster, SpellIds.GiftOfLife2, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_nitro_boosts : SpellScript +{ + public override bool Load() + { + if (GetCastItem() == null) + return false; + return true; + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NitroBoostsSuccess, SpellIds.NitroBoostsBackfire); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + bool success = true; + if (!caster.GetMap().IsDungeon()) + success = RandomHelper.randChance(95); // nitro boosts can only fail in flying-enabled locations on 3.3.5 + caster.CastSpell(caster, success ? SpellIds.NitroBoostsSuccess : SpellIds.NitroBoostsBackfire, GetCastItem()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_nitro_boosts_backfire : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NitroBoostsParachute); + } + + void HandleApply(AuraEffect effect, AuraEffectHandleModes mode) + { + lastZ = GetTarget().GetPositionZ(); + } + + void HandlePeriodicDummy(AuraEffect effect) + { + PreventDefaultAction(); + float curZ = GetTarget().GetPositionZ(); + if (curZ < lastZ) + { + if (RandomHelper.randChance(80)) // we don't have enough sniffs to verify this, guesstimate + GetTarget().CastSpell(GetTarget(), SpellIds.NitroBoostsParachute, effect); + GetAura().Remove(); + } + else + lastZ = curZ; + } + + public override void Register() + { + OnEffectApply.Add(new(HandleApply, 1, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + OnEffectPeriodic.Add(new(HandlePeriodicDummy, 1, AuraType.PeriodicTriggerSpell)); + } + + float lastZ = MapConst.InvalidHeight; +} + +[Script] +class spell_item_rocket_boots : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RocketBootsProc); + } + + void HandleDummy(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + caster.GetSpellHistory().ResetCooldown(SpellIds.RocketBootsProc); + caster.CastSpell(caster, SpellIds.RocketBootsProc, true); + } + + SpellCastResult CheckCast() + { + if (GetCaster().IsInWater()) + return SpellCastResult.OnlyAbovewater; + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 67489 - Runic Healing Injector +class spell_item_runic_healing_injector : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleHeal(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + if (caster != null && caster.HasSkill(SkillType.Engineering)) + SetHitHeal((int)(GetHitHeal() * 1.25f)); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHeal, 0, SpellEffectName.Heal)); + } +} + +[Script] +class spell_item_pygmy_oil : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PygmyOilPygmyAura, SpellIds.PygmyOilSmallerAura); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Aura aura = caster.GetAura(SpellIds.PygmyOilPygmyAura); + if (aura != null) + aura.RefreshDuration(); + else + { + aura = caster.GetAura(SpellIds.PygmyOilSmallerAura); + if (aura == null || aura.GetStackAmount() < 5 || !RandomHelper.randChance(50)) + caster.CastSpell(caster, SpellIds.PygmyOilSmallerAura, true); + else + { + aura.Remove(); + caster.CastSpell(caster, SpellIds.PygmyOilPygmyAura, true); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_unusual_compass : SpellScript +{ + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + caster.SetFacingTo(RandomHelper.FRand(0.0f, 2.0f * MathF.PI)); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_chicken_cover : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChickenNet, SpellIds.CaptureChickenEscape) && + Global.ObjectMgr.GetQuestTemplate(MiscConst.QuestChickenParty) != null && + Global.ObjectMgr.GetQuestTemplate(MiscConst.QuestFlownTheCoop) != null; + } + + void HandleDummy(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + Unit target = GetHitUnit(); + if (target != null) + { + if (!target.HasAura(SpellIds.ChickenNet) && (caster.GetQuestStatus(MiscConst.QuestChickenParty) == QuestStatus.Incomplete || caster.GetQuestStatus(MiscConst.QuestFlownTheCoop) == QuestStatus.Incomplete)) + { + caster.CastSpell(caster, SpellIds.CaptureChickenEscape, true); + target.KillSelf(); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_muisek_vessel : SpellScript +{ + void HandleDummy(uint effIndex) + { + Creature target = GetHitCreature(); + if (target != null) + if (target.IsDead()) + target.DespawnOrUnsummon(); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] +class spell_item_greatmothers_soulcatcher : SpellScript +{ + void HandleDummy(uint effIndex) + { + if (GetHitUnit() != null) + GetCaster().CastSpell(GetCaster(), SpellIds.ForceCastSummonGnomeSoul); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// Item - 49310: Purified Shard of the Scale +// 69755 - Purified Shard of the Scale - Equip Effect + +// Item - 49488: Shiny Shard of the Scale +// 69739 - Shiny Shard of the Scale - Equip Effect +[Script("spell_item_purified_shard_of_the_scale", SpellIds.PurifiedCauterizingHeal, SpellIds.PurifiedSearingFlames)] +[Script("spell_item_shiny_shard_of_the_scale", SpellIds.ShinyCauterizingHeal, SpellIds.ShinySearingFlames)] +class spell_item_shard_of_the_scale(uint HealProcSpellId, uint DamageProcSpellId) : AuraScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(HealProcSpellId, DamageProcSpellId); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + if (eventInfo.GetTypeMask() & new ProcFlagsInit(ProcFlags.DealHelpfulSpell)) + caster.CastSpell(target, HealProcSpellId, aurEff); + + if (eventInfo.GetTypeMask() & new ProcFlagsInit(ProcFlags.DealHarmfulSpell)) + caster.CastSpell(target, DamageProcSpellId, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] +class spell_item_soul_preserver : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SoulPreserverDruid, SpellIds.SoulPreserverPaladin, SpellIds.SoulPreserverPriest, SpellIds.SoulPreserverShaman); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + + switch (caster.GetClass()) + { + case Class.Druid: + caster.CastSpell(caster, SpellIds.SoulPreserverDruid, aurEff); + break; + case Class.Paladin: + caster.CastSpell(caster, SpellIds.SoulPreserverPaladin, aurEff); + break; + case Class.Priest: + caster.CastSpell(caster, SpellIds.SoulPreserverPriest, aurEff); + break; + case Class.Shaman: + caster.CastSpell(caster, SpellIds.SoulPreserverShaman, aurEff); + break; + default: + break; + } + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +// Item - 34678: Shattered Sun Pendant of Acumen +// 45481 - Sunwell Exalted Caster Neck + +// Item - 34679: Shattered Sun Pendant of Might +// 45482 - Sunwell Exalted Melee Neck + +// Item - 34680: Shattered Sun Pendant of Resolve +// 45483 - Sunwell Exalted Tank Neck + +// Item - 34677: Shattered Sun Pendant of Restoration +// 45484 Sunwell Exalted Healer Neck +[Script("spell_item_sunwell_exalted_caster_neck", SpellIds.LightsWrath, SpellIds.ArcaneBolt)] +[Script("spell_item_sunwell_exalted_melee_neck", SpellIds.LightsStrength, SpellIds.ArcaneStrike)] +[Script("spell_item_sunwell_exalted_tank_neck", SpellIds.LightsWard, SpellIds.ArcaneInsight)] +[Script("spell_item_sunwell_exalted_healer_neck", SpellIds.LightsSalvation, SpellIds.ArcaneSurge)] +class spell_item_sunwell_neck(uint Aldors, uint Scryers) : AuraScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(Aldors, Scryers) && + CliDB.FactionStorage.ContainsKey(MiscConst.FactionAldor) && + CliDB.FactionStorage.ContainsKey(MiscConst.FactionScryers); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetActor().GetTypeId() != TypeId.Player) + return false; + return true; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Player player = eventInfo.GetActor().ToPlayer(); + Unit target = eventInfo.GetProcTarget(); + + // Aggression checks are in the spell system... just cast and forget + if (player.GetReputationRank(MiscConst.FactionAldor) == ReputationRank.Exalted) + player.CastSpell(target, Aldors, aurEff); + + if (player.GetReputationRank(MiscConst.FactionScryers) == ReputationRank.Exalted) + player.CastSpell(target, Scryers, aurEff); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] +class spell_item_toy_train_set_pulse : SpellScript +{ + void HandleDummy(uint index) + { + Player target = GetHitUnit().ToPlayer(); + if (target != null) + { + target.HandleEmoteCommand(Emote.OneshotTrain); + var soundEntry = Global.DB2Mgr.GetTextSoundEmoteFor((uint)TextEmotes.Train, target.GetRace(), target.GetNativeGender(), target.GetClass()); + if (soundEntry != null) + target.PlayDistanceSound(soundEntry.SoundId); + } + } + + void HandleTargets(List targetList) + { + targetList.RemoveAll(obj => obj.GetTypeId() != TypeId.Player); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); + OnObjectAreaTargetSelect.Add(new(HandleTargets, SpellConst.EffectAll, Targets.UnitSrcAreaAlly)); + } +} + +[Script] +class spell_item_death_choice : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DeathChoiceNormalStrength, SpellIds.DeathChoiceNormalAgility, SpellIds.DeathChoiceHeroicStrength, SpellIds.DeathChoiceHeroicAgility); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + float str = caster.GetStat(Stats.Strength); + float agi = caster.GetStat(Stats.Agility); + + switch (aurEff.GetId()) + { + case SpellIds.DeathChoiceNormalAura: + { + if (str > agi) + caster.CastSpell(caster, SpellIds.DeathChoiceNormalStrength, aurEff); + else + caster.CastSpell(caster, SpellIds.DeathChoiceNormalAgility, aurEff); + break; + } + case SpellIds.DeathChoiceHeroicAura: + { + if (str > agi) + caster.CastSpell(caster, SpellIds.DeathChoiceHeroicStrength, aurEff); + else + caster.CastSpell(caster, SpellIds.DeathChoiceHeroicAgility, aurEff); + break; + } + default: + break; + } + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script("spell_item_lightning_capacitor", SpellIds.LightningCapacitorStack, SpellIds.LightningCapacitorTrigger)] +[Script("spell_item_thunder_capacitor", SpellIds.ThunderCapacitorStack, SpellIds.ThunderCapacitorTrigger)] +[Script("spell_item_toc25_normal_caster_trinket", SpellIds.TOC25CasterTrinketNormalStack, SpellIds.TOC25CasterTrinketNormalTrigger)] +[Script("spell_item_toc25_heroic_caster_trinket", SpellIds.TOC25CasterTrinketHeroicStack, SpellIds.TOC25CasterTrinketHeroicTrigger)] +class spell_item_trinket_stack(uint stackSpell, uint triggerSpell) : AuraScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(stackSpell, triggerSpell); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + + caster.CastSpell(caster, stackSpell, aurEff); // cast the stack + + Aura dummy = caster.GetAura(stackSpell); // retrieve aura + + //dont do anything if it's not the right amount of stacks; + if (dummy == null || dummy.GetStackAmount() < aurEff.GetAmount()) + return; + + // if right amount, remove the aura and cast real trigger + caster.RemoveAurasDueToSpell(stackSpell); + Unit target = eventInfo.GetActionTarget(); + if (target != null) + caster.CastSpell(target, triggerSpell, aurEff); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(stackSpell); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 57345 - Darkmoon Card: Greatness +class spell_item_darkmoon_card_greatness : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DarkmoonCardStrength, SpellIds.DarkmoonCardAgility, SpellIds.DarkmoonCardIntellect, SpellIds.DarkmoonCardVersatility); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + float str = caster.GetStat(Stats.Strength); + float agi = caster.GetStat(Stats.Agility); + float intl = caster.GetStat(Stats.Intellect); + float vers = 0.0f; // caster.GetStat(StatVersatility); + float stat = 0.0f; + + uint spellTrigger = SpellIds.DarkmoonCardStrength; + + if (str > stat) + { + spellTrigger = SpellIds.DarkmoonCardStrength; + stat = str; + } + + if (agi > stat) + { + spellTrigger = SpellIds.DarkmoonCardAgility; + stat = agi; + } + + if (intl > stat) + { + spellTrigger = SpellIds.DarkmoonCardIntellect; + stat = intl; + } + + if (vers > stat) + { + spellTrigger = SpellIds.DarkmoonCardVersatility; + stat = vers; + } + + caster.CastSpell(caster, spellTrigger, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 27522,40336 - Mana Drain +class spell_item_mana_drain : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ManaDrainEnergize, SpellIds.ManaDrainLeech); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetActionTarget(); + + if (caster.IsAlive()) + caster.CastSpell(caster, SpellIds.ManaDrainEnergize, aurEff); + + if (target != null && target.IsAlive()) + caster.CastSpell(target, SpellIds.ManaDrainLeech, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 51640 - Taunt Flag Targeting +class spell_item_taunt_flag_targeting : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TauntFlag) && + CliDB.BroadcastTextStorage.ContainsKey(MiscConst.EmotePlantsFlag); + } + + void FilterTargets(List targets) + { + targets.RemoveAll(obj => obj.GetTypeId() != TypeId.Player && obj.GetTypeId() != TypeId.Corpse); + + if (targets.Empty()) + { + FinishCast(SpellCastResult.NoValidTargets); + return; + } + + targets.RandomResize(1); + } + + void HandleDummy(uint effIndex) + { + // we *really* want the unit implementation here + // it sends a packet like seen on sniff + GetCaster().TextEmote(MiscConst.EmotePlantsFlag, GetHitUnit(), false); + + GetCaster().CastSpell(GetHitUnit(), SpellIds.TauntFlag, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.CorpseSrcAreaEnemy)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 29830 - Mirren's Drinking Hat +class spell_item_mirrens_drinking_hat : SpellScript +{ + void HandleScriptEffect(uint effIndex) + { + uint spellId = 0; + switch (RandomHelper.URand(1, 6)) + { + case 1: + case 2: + case 3: + spellId = SpellIds.LochModanLager; break; + case 4: + case 5: + spellId = SpellIds.StouthammerLite; break; + case 6: + spellId = SpellIds.AeriePeakPaleAle; break; + default: + return; + } + + Unit caster = GetCaster(); + caster.CastSpell(caster, spellId, GetSpell()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 13180 - Gnomish Mind Control Cap +class spell_item_mind_control_cap : SpellScript +{ + public override bool Load() + { + if (GetCastItem() == null) + return false; + return true; + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GnomishMindControlCap, SpellIds.Dullard); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target != null) + { + if (RandomHelper.randChance(MiscConst.RollChanceNoBackfire)) + caster.CastSpell(target, RandomHelper.randChance(MiscConst.RollChanceDullard) ? SpellIds.Dullard : SpellIds.GnomishMindControlCap, GetCastItem()); + else + target.CastSpell(caster, SpellIds.GnomishMindControlCap, true); // backfire - 5% chance + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 8344 - Universal Remote (Gnomish Universal Remote) +class spell_item_universal_remote : SpellScript +{ + public override bool Load() + { + if (GetCastItem() == null) + return false; + return true; + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ControlMachine, SpellIds.MobilityMalfunction, SpellIds.TargetLock); + } + + void HandleDummy(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) + { + uint chance = RandomHelper.URand(0, 99); + if (chance < 15) + GetCaster().CastSpell(target, SpellIds.TargetLock, GetCastItem()); + else if (chance < 25) + GetCaster().CastSpell(target, SpellIds.MobilityMalfunction, GetCastItem()); + else + GetCaster().CastSpell(target, SpellIds.ControlMachine, GetCastItem()); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// Item - 19950: Zandalarian Hero Charm +// 24658 - Unstable Power + +// Item - 19949: Zandalarian Hero Medallion +// 24661 - Restless Strength +[Script("spell_item_unstable_power", SpellIds.UnstablePowerAuraStack)] +[Script("spell_item_restless_strength", SpellIds.RestlessStrengthAuraStack)] +class spell_item_zandalarian_charm_AuraScript(uint spellId) : AuraScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(spellId); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo != null && spellInfo.Id != m_scriptSpellId) + return true; + + return false; + } + + void HandleStackDrop(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().RemoveAuraFromStack(spellId); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleStackDrop, 0, AuraType.Dummy)); + } +} + +[Script] +class spell_item_artifical_stamina : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + public override bool Load() + { + return GetOwner().IsPlayer(); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Item artifact = GetOwner().ToPlayer().GetItemByGuid(GetAura().GetCastItemGUID()); + if (artifact != null) + amount = (int)(GetEffectInfo(1).BasePoints * artifact.GetTotalPurchasedArtifactPowers() / 100); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModTotalStatPercentage)); + } +} + +[Script] +class spell_item_artifical_damage : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + public override bool Load() + { + return GetOwner().IsPlayer(); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Item artifact = GetOwner().ToPlayer().GetItemByGuid(GetAura().GetCastItemGUID()); + if (artifact != null) + amount = (int)(GetSpellInfo().GetEffect(1).BasePoints * artifact.GetTotalPurchasedArtifactPowers() / 100); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModDamagePercentDone)); + } +} + +[Script] // 28200 - Ascendance +class spell_item_talisman_of_ascendance : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TalismanOfAscendance); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 29602 - Jom Gabbar +class spell_item_jom_gabbar : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.JomGabbar); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 45040 - Battle Trance +class spell_item_battle_trance : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BattleTrance); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 90900 - World-Queller Focus +class spell_item_world_queller_focus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.WorldQuellerFocus); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +// 118089 - Azure Water Strider +// 127271 - Crimson Water Strider +// 127272 - Orange Water Strider +// 127274 - Jade Water Strider +[Script] // 127278 - Golden Water Strider +class spell_item_water_strider : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(GetSpellInfo().GetEffect(1).TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.Mounted, AuraEffectHandleModes.Real)); + } +} + +// 144671 - Brutal Kinship +[Script] // 145738 - Brutal Kinship +class spell_item_brutal_kinship : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BrutalKinship1, SpellIds.BrutalKinship2); + } + + void OnRemove(AuraEffect effect, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(effect.GetSpellEffectInfo().TriggerSpell); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnRemove, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.Real)); + } +} + +[Script] // 45051 - Mad Alchemist's Potion (34440) +class spell_item_mad_alchemists_potion : SpellScript +{ + void SecondaryEffect() + { + List availableElixirs = + [ + // Battle Elixirs + 33720, // Onslaught Elixir (28102) + 54452, // Adept's Elixir (28103) + 33726, // Elixir of Mastery (28104) + 28490, // Elixir of Major Strength (22824) + 28491, // Elixir of Healing Power (22825) + 28493, // Elixir of Major Frost Power (22827) + 54494, // Elixir of Major Agility (22831) + 28501, // Elixir of Major Firepower (22833) + 28503,// Elixir of Major Shadow Power (22835) + 38954, // Fel Strength Elixir (31679) + // Guardian Elixirs + 39625, // Elixir of Major Fortitude (32062) + 39626, // Earthen Elixir (32063) + 39627, // Elixir of Draenic Wisdom (32067) + 39628, // Elixir of Ironskin (32068) + 28502, // Elixir of Major Defense (22834) + 28514, // Elixir of Empowerment (22848) + // Other + 28489, // Elixir of Camouflage (22823) + 28496 // Elixir of the Searching Eye (22830) + ]; + + Unit target = GetCaster(); + + if (target.GetPowerType() == PowerType.Mana) + availableElixirs.Add(28509); // Elixir of Major Mageblood (22840) + + uint chosenElixir = availableElixirs.SelectRandom(); + + bool useElixir = true; + + SpellGroup chosenSpellGroup = SpellGroup.None; + if (Global.SpellMgr.IsSpellMemberOfSpellGroup(chosenElixir, SpellGroup.ElixirBattle)) + chosenSpellGroup = SpellGroup.ElixirBattle; + if (Global.SpellMgr.IsSpellMemberOfSpellGroup(chosenElixir, SpellGroup.ElixirGuardian)) + chosenSpellGroup = SpellGroup.ElixirGuardian; + // If another spell of the same group is already active the elixir should not be cast + if (chosenSpellGroup != SpellGroup.None) + { + var auraMap = target.GetAppliedAuras(); + foreach (var (_, app) in auraMap) + { + uint spellId = app.GetBase().GetId(); + if (Global.SpellMgr.IsSpellMemberOfSpellGroup(spellId, chosenSpellGroup) && spellId != chosenElixir) + { + useElixir = false; + break; + } + } + } + + if (useElixir) + target.CastSpell(target, chosenElixir, GetCastItem()); + } + + public override void Register() + { + AfterCast.Add(new(SecondaryEffect)); + } +} + +[Script] // 53750 - Crazy Alchemist's Potion (40077) +class spell_item_crazy_alchemists_potion : SpellScript +{ + void SecondaryEffect() + { + List availableElixirs = + [ + 43185, // Runic Healing Potion (33447) + 53750, // Crazy Alchemist's Potion (40077) + 53761, // Powerful Rejuvenation Potion (40087) + 53762, // Indestructible Potion (40093) + 53908, // Potion of Speed (40211) + 53909, // Potion of Wild Magic (40212) + 53910, // Mighty Arcane Protection Potion (40213) + 53911, // Mighty Fire Protection Potion (40214) + 53913, // Mighty Frost Protection Potion (40215) + 53914, // Mighty Nature Protection Potion (40216) + 53915 // Mighty Shadow Protection Potion (40217) + ]; + + Unit target = GetCaster(); + + if (!target.IsInCombat()) + availableElixirs.Add(53753); // Potion of Nightmares (40081) + if (target.GetPowerType() == PowerType.Mana) + availableElixirs.Add(43186); // Runic Mana Potion(33448) + + uint chosenElixir = availableElixirs.SelectRandom(); + + target.CastSpell(target, chosenElixir, GetCastItem()); + } + + public override void Register() + { + AfterCast.Add(new(SecondaryEffect)); + } +} + +[Script] // 21149 - Egg Nog +class spell_item_eggnog : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EggNogReindeer, SpellIds.EggNogSnowman); + } + + void HandleScript(uint effIndex) + { + if (RandomHelper.randChance(40)) + GetCaster().CastSpell(GetHitUnit(), RandomHelper.randChance(50) ? SpellIds.EggNogReindeer : SpellIds.EggNogSnowman, GetCastItem()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 2, SpellEffectName.Inebriate)); + } +} + +// 208051 - Sephuz's Secret +// 234867 - Sephuz's Secret +[Script] // 236763 - Sephuz's Secret +class spell_item_sephuzs_secret : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SephuzsSecretCooldown); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + if (GetUnitOwner().HasAura(SpellIds.SephuzsSecretCooldown)) + return false; + + if (eventInfo.GetHitMask().HasAnyFlag(ProcFlagsHit.Interrupt | ProcFlagsHit.Dispel)) + return true; + + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + bool isCrowdControl = procSpell.GetSpellInfo().HasAura(AuraType.ModConfuse) + || procSpell.GetSpellInfo().HasAura(AuraType.ModFear) + || procSpell.GetSpellInfo().HasAura(AuraType.ModStun) + || procSpell.GetSpellInfo().HasAura(AuraType.ModPacify) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) + || procSpell.GetSpellInfo().HasAura(AuraType.ModSilence) + || procSpell.GetSpellInfo().HasAura(AuraType.ModPacifySilence) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2); + + if (!isCrowdControl) + return false; + + return true; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + PreventDefaultAction(); + + GetUnitOwner().CastSpell(GetUnitOwner(), SpellIds.SephuzsSecretCooldown, new CastSpellExtraArgs(TriggerCastFlags.FullMask)); + GetUnitOwner().CastSpell(procInfo.GetProcTarget(), aurEff.GetSpellEffectInfo().TriggerSpell, new CastSpellExtraArgs(aurEff).SetTriggeringSpell(procInfo.GetProcSpell())); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 215266 - Fragile Echoes +class spell_item_amalgams_seventh_spine : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FragileEchoesMonk, SpellIds.FragileEchoesShaman, SpellIds.FragileEchoesPriestDiscipline, SpellIds.FragileEchoesPaladin, SpellIds.FragileEchoesDruid, SpellIds.FragileEchoesPriestHoly, SpellIds.FragileEchoesEvoker); + } + + void UpdateSpecAura(bool apply) + { + Player target = GetUnitOwner().ToPlayer(); + if (target == null) + return; + + void updateAuraIfInCorrectSpec(ChrSpecialization spec, uint aura) + { + if (!apply || target.GetPrimarySpecialization() != spec) + target.RemoveAurasDueToSpell(aura); + else if (!target.HasAura(aura)) + target.CastSpell(target, aura, GetEffect(0)); + } + + switch (target.GetClass()) + { + case Class.Monk: + updateAuraIfInCorrectSpec(ChrSpecialization.MonkMistweaver, SpellIds.FragileEchoesMonk); + break; + case Class.Shaman: + updateAuraIfInCorrectSpec(ChrSpecialization.ShamanRestoration, SpellIds.FragileEchoesShaman); + break; + case Class.Priest: + updateAuraIfInCorrectSpec(ChrSpecialization.PriestDiscipline, SpellIds.FragileEchoesPriestDiscipline); + updateAuraIfInCorrectSpec(ChrSpecialization.PriestHoly, SpellIds.FragileEchoesPriestHoly); + break; + case Class.Paladin: + updateAuraIfInCorrectSpec(ChrSpecialization.PaladinHoly, SpellIds.FragileEchoesPaladin); + break; + case Class.Druid: + updateAuraIfInCorrectSpec(ChrSpecialization.DruidRestoration, SpellIds.FragileEchoesDruid); + break; + case Class.Evoker: + updateAuraIfInCorrectSpec(ChrSpecialization.EvokerPreservation, SpellIds.FragileEchoesEvoker); + break; + default: + break; + } + } + + void HandleHeartbeat() + { + UpdateSpecAura(true); + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + UpdateSpecAura(false); + } + + public override void Register() + { + OnHeartbeat.Add(new(HandleHeartbeat)); + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 215267 - Fragile Echo +class spell_item_amalgams_seventh_spine_mana_restore : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FragileEchoEnergize); + } + + void TriggerManaRestoration(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit caster = GetCaster(); + if (caster == null) + return; + + AuraEffect trinketEffect = caster.GetAuraEffect(aurEff.GetSpellEffectInfo().TriggerSpell, 0); + if (trinketEffect != null) + caster.CastSpell(caster, SpellIds.FragileEchoEnergize, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, trinketEffect.GetAmount())); + } + + public override void Register() + { + AfterEffectRemove.Add(new(TriggerManaRestoration, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 228445 - March of the Legion +class spell_item_set_march_of_the_legion : AuraScript +{ + bool IsDemon(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().GetCreatureType() == CreatureType.Demon; + } + + public override void Register() + { + DoCheckEffectProc.Add(new(IsDemon, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 234113 - Arrogance (used by item 142171 - Seal of Darkshire Nobility) +class spell_item_seal_of_darkshire_nobility : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)) + && ValidateSpellInfo(spellInfo.GetEffect(1).TriggerSpell); + } + + bool CheckCooldownAura(ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() != null && !eventInfo.GetProcTarget().HasAura(GetEffectInfo(1).TriggerSpell, GetTarget().GetGUID()); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckCooldownAura)); + } +} + +[Script] // 247625 - March of the Legion +class spell_item_lightblood_elixir : AuraScript +{ + bool IsDemon(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() != null && eventInfo.GetProcTarget().GetCreatureType() == CreatureType.Demon; + } + + public override void Register() + { + DoCheckEffectProc.Add(new(IsDemon, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 253287 - Highfather's Timekeeping +class spell_item_highfathers_machination : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HighfathersTimekeepingHeal); + } + + bool CheckHealth(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo() != null && GetTarget().HealthBelowPctDamaged(aurEff.GetAmount(), eventInfo.GetDamageInfo().GetDamage()); + } + + void Heal(AuraEffect aurEff, ProcEventInfo procInfo) + { + PreventDefaultAction(); + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.HighfathersTimekeepingHeal, aurEff); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckHealth, 0, AuraType.Dummy)); + OnEffectProc.Add(new(Heal, 0, AuraType.Dummy)); + } +} + +[Script] // 253323 - Shadow Strike +class spell_item_seeping_scourgewing : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowStrikeAoeCheck); + } + + void TriggerIsolatedStrikeCheck(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.ShadowStrikeAoeCheck, + new CastSpellExtraArgs(aurEff).SetTriggeringSpell(eventInfo.GetProcSpell())); + } + + public override void Register() + { + AfterEffectProc.Add(new(TriggerIsolatedStrikeCheck, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 255861 - Shadow Strike +class spell_item_seeping_scourgewing_aoe_check : SpellScript +{ + void TriggerAdditionalDamage() + { + if (GetUnitTargetCountForEffect(0) > 1) + return; + + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.OriginalCastId = GetSpell().m_originalCastId; + if (GetSpell().m_castItemLevel >= 0) + args.OriginalCastItemLevel = GetSpell().m_castItemLevel; + + GetCaster().CastSpell(GetHitUnit(), SpellIds.IsolatedStrike, args); + } + + public override void Register() + { + AfterHit.Add(new(TriggerAdditionalDamage)); + } +} + +[Script] // 295175 - Spiteful Binding +class spell_item_grips_of_forsaken_sanity : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + bool CheckHealth(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActor().GetHealthPct() >= (float)GetEffectInfo(1).CalcValue(); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckHealth, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 302385 - Resurrect Health +class spell_item_zanjir_scaleguard_greatcloak : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().HasEffect(SpellEffectName.Resurrect); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script("spell_item_shiver_venom_crossbow", SpellIds.ShiveringBolt)] // 303358 Venomous Bolt +[Script("spell_item_shiver_venom_lance", SpellIds.VenomousLance)] // 303361 Shivering Lance +class spell_item_shiver_venom_weapon_proc(uint additionalProcSpellId) : AuraScript() +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShiverVenom, additionalProcSpellId); + } + + void HandleAdditionalProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + if (procInfo.GetProcTarget().HasAura(SpellIds.ShiverVenom)) + procInfo.GetActor().CastSpell(procInfo.GetProcTarget(), additionalProcSpellId, new CastSpellExtraArgs(aurEff) + .AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount()) + .SetTriggeringSpell(procInfo.GetProcSpell())); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleAdditionalProc, 1, AuraType.Dummy)); + } +} + +[Script] // 302774 - Arcane Tempest +class spell_item_phial_of_the_arcane_tempest_damage : SpellScript +{ + void ModifyStacks() + { + if (GetUnitTargetCountForEffect(0) != 1 || GetTriggeringSpell() == null) + return; + + AuraEffect aurEff = GetCaster().GetAuraEffect(GetTriggeringSpell().Id, 0); + if (aurEff != null) + { + aurEff.GetBase().ModStackAmount(1, AuraRemoveMode.None, false); + aurEff.CalculatePeriodic(GetCaster(), false); + } + } + + public override void Register() + { + AfterCast.Add(new(ModifyStacks)); + } +} + +[Script] // 302769 - Arcane Tempest +class spell_item_phial_of_the_arcane_tempest_periodic : AuraScript +{ + void CalculatePeriod(AuraEffect aurEff, ref bool isPeriodic, ref int period) + { + period -= (GetStackAmount() - 1) * 300; + } + + public override void Register() + { + DoEffectCalcPeriodic.Add(new(CalculatePeriod, 0, AuraType.PeriodicTriggerSpell)); + } +} + +// 410530 - Mettle +[Script] // 410964 - Mettle +class spell_item_infurious_crafted_gear_mettle : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MettleCooldown); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (GetTarget().HasAura(SpellIds.MettleCooldown)) + return false; + + if (eventInfo.GetHitMask().HasAnyFlag(ProcFlagsHit.Interrupt | ProcFlagsHit.Dispel)) + return true; + + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + bool isCrowdControl = procSpell.GetSpellInfo().HasAura(AuraType.ModConfuse) + || procSpell.GetSpellInfo().HasAura(AuraType.ModFear) + || procSpell.GetSpellInfo().HasAura(AuraType.ModStun) + || procSpell.GetSpellInfo().HasAura(AuraType.ModPacify) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot) + || procSpell.GetSpellInfo().HasAura(AuraType.ModSilence) + || procSpell.GetSpellInfo().HasAura(AuraType.ModPacifySilence) + || procSpell.GetSpellInfo().HasAura(AuraType.ModRoot2); + + if (!isCrowdControl) + return false; + + return eventInfo.GetActionTarget().HasAura(aura => aura.GetCastId() == procSpell.m_castId); + } + + void TriggerCooldown(ProcEventInfo eventInfo) + { + GetTarget().CastSpell(GetTarget(), SpellIds.MettleCooldown, true); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + AfterProc.Add(new(TriggerCooldown)); + } +} \ No newline at end of file diff --git a/Source/Scripts/Spells/Mage.cs b/Source/Scripts/Spells/Mage.cs index 719eb2c94..53146830a 100644 --- a/Source/Scripts/Spells/Mage.cs +++ b/Source/Scripts/Spells/Mage.cs @@ -1,5 +1,5 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Framework.Dynamic; @@ -11,1480 +11,1788 @@ using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using static Global; -namespace Scripts.Spells.Mage +namespace Scripts.Spells.Mage; + +struct SpellIds { - struct SpellIds + public const uint AlterTimeAura = 110909; + public const uint AlterTimeVisual = 347402; + public const uint ArcaneAlterTimeAura = 342246; + public const uint ArcaneBarrageEnergize = 321529; + public const uint ArcaneBarrageR3 = 321526; + public const uint ArcaneCharge = 36032; + public const uint ArcaneMage = 137021; + public const uint BlazingBarrierTrigger = 235314; + public const uint Blink = 1953; + public const uint BlizzardDamage = 190357; + public const uint BlizzardSlow = 12486; + public const uint CauterizeDot = 87023; + public const uint Cauterized = 87024; + public const uint Chilled = 205708; + public const uint CometStormDamage = 153596; + public const uint CometStormVisual = 228601; + public const uint ConeOfCold = 120; + public const uint ConeOfColdSlow = 212792; + public const uint ConjureRefreshment = 116136; + public const uint ConjureRefreshmentTable = 167145; + public const uint DragonhawkForm = 32818; + public const uint EtherealBlink = 410939; + public const uint EverwarmSocks = 320913; + public const uint FeelTheBurn = 383391; + public const uint FingersOfFrost = 44544; + public const uint FireBlast = 108853; + public const uint Firestarter = 205026; + public const uint FlamePatchAreatrigger = 205470; + public const uint FlamePatchDamage = 205472; + public const uint FlamePatchTalent = 205037; + public const uint FlurryDamage = 228596; + public const uint FreneticSpeed = 236060; + public const uint FrostNova = 122; + public const uint GiraffeForm = 32816; + public const uint IceBarrier = 11426; + public const uint IceBlock = 45438; + public const uint Ignite = 12654; + public const uint ImprovedCombustion = 383967; + public const uint ImprovedScorch = 383608; + public const uint IncantersFlow = 116267; + public const uint LivingBombExplosion = 44461; + public const uint LivingBombPeriodic = 217694; + public const uint ManaSurge = 37445; + public const uint MasterOfTime = 342249; + public const uint MeteorAreatrigger = 177345; + public const uint MeteorBurnDamage = 155158; + public const uint MeteorMissile = 153564; + public const uint MoltenFury = 458910; + public const uint PhoenixFlames = 257541; + public const uint RadiantSparkProcBlocker = 376105; + public const uint RayOfFrostBonus = 208141; + public const uint RayOfFrostFingersOfFrost = 269748; + public const uint Reverberate = 281482; + public const uint RingOfFrostDummy = 91264; + public const uint RingOfFrostFreeze = 82691; + public const uint RingOfFrostSummon = 113724; + public const uint Scald = 450746; + public const uint SerpentForm = 32817; + public const uint SheepForm = 32820; + public const uint Shimmer = 212653; + public const uint Slow = 31589; + public const uint SpontaneousCombustion = 451875; + public const uint SquirrelForm = 32813; + public const uint Supernova = 157980; + public const uint TempestBarrierAbsorb = 382290; + public const uint WorgenForm = 32819; + public const uint SpellPetNetherwindsFatigued = 160455; + public const uint IceLanceTrigger = 228598; + public const uint ThermalVoid = 155149; + public const uint IcyVeins = 12472; + public const uint ChainReactionDummy = 278309; + public const uint ChainReaction = 278310; + public const uint TouchOfTheMagiExplode = 210833; + public const uint WintersChill = 228358; +} + +// 110909 - Alter Time Aura +[Script] // 342246 - Alter Time Aura +class spell_mage_alter_time_aura : AuraScript +{ + ulong _health; + Position _pos; + + public override bool Validate(SpellInfo spellInfo) { - public const uint AlterTimeAura = 110909; - public const uint AlterTimeVisual = 347402; - public const uint ArcaneAlterTimeAura = 342246; - public const uint ArcaneBarrageEnergize = 321529; - public const uint ArcaneBarrageR3 = 321526; - public const uint ArcaneCharge = 36032; - public const uint ArcaneMage = 137021; - public const uint BlazingBarrierTrigger = 235314; - public const uint Blink = 1953; - public const uint BlizzardDamage = 190357; - public const uint BlizzardSlow = 12486; - public const uint CauterizeDot = 87023; - public const uint Cauterized = 87024; - public const uint Chilled = 205708; - public const uint CometStormDamage = 153596; - public const uint CometStormVisual = 228601; - public const uint ConeOfCold = 120; - public const uint ConeOfColdSlow = 212792; - public const uint ConjureRefreshment = 116136; - public const uint ConjureRefreshmentTable = 167145; - public const uint DragonhawkForm = 32818; - public const uint EtherealBlink = 410939; - public const uint EverwarmSocks = 320913; - public const uint FeelTheBurn = 383391; - public const uint FingersOfFrost = 44544; - public const uint FireBlast = 108853; - public const uint FlurryDamage = 228596; - public const uint Firestarter = 205026; - public const uint FrostNova = 122; - public const uint GiraffeForm = 32816; - public const uint IceBarrier = 11426; - public const uint IceBlock = 45438; - public const uint Ignite = 12654; - public const uint IncantersFlow = 116267; - public const uint LivingBombExplosion = 44461; - public const uint LivingBombPeriodic = 217694; - public const uint ManaSurge = 37445; - public const uint MasterOfTime = 342249; - public const uint RadiantSparkProcBlocker = 376105; - public const uint RayOfFrostBonus = 208141; - public const uint RayOfFrostFingersOfFrost = 269748; - public const uint Reverberate = 281482; - public const uint RingOfFrostDummy = 91264; - public const uint RingOfFrostFreeze = 82691; - public const uint RingOfFrostSummon = 113724; - public const uint SerpentForm = 32817; - public const uint SheepForm = 32820; - public const uint Shimmer = 212653; - public const uint Slow = 31589; - public const uint SquirrelForm = 32813; - public const uint Supernova = 157980; - public const uint WorgenForm = 32819; - public const uint PetNetherwindsFatigued = 160455; - public const uint IceLanceTrigger = 228598; - public const uint ThermalVoid = 155149; - public const uint IcyVeins = 12472; - public const uint ChainReactionDummy = 278309; - public const uint ChainReaction = 278310; - public const uint TouchOfTheMagiExplode = 210833; - public const uint WintersChill = 228358; + return ValidateSpellInfo(SpellIds.AlterTimeVisual, SpellIds.MasterOfTime, SpellIds.Blink); } - // 110909 - Alter Time Aura - [Script] // 342246 - Alter Time Aura - class spell_mage_alter_time_AuraScript : AuraScript + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - ulong _health; - Position _pos; + Unit unit = GetTarget(); + _health = unit.GetHealth(); + _pos = unit.GetPosition(); + } - public override bool Validate(SpellInfo spellInfo) + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit unit = GetTarget(); + if (unit.GetDistance(_pos) <= 100.0f && GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) { - return ValidateSpellInfo(SpellIds.AlterTimeVisual, SpellIds.MasterOfTime, SpellIds.Blink); - } + unit.SetHealth(_health); + unit.NearTeleportTo(_pos); - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit unit = GetTarget(); - _health = unit.GetHealth(); - _pos = unit.GetPosition(); - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit unit = GetTarget(); - if (unit.GetDistance(_pos) <= 100.0f && GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) + if (unit.HasAura(SpellIds.MasterOfTime)) { - unit.SetHealth(_health); - unit.NearTeleportTo(_pos); - - if (unit.HasAura(SpellIds.MasterOfTime)) - { - SpellInfo blink = SpellMgr.GetSpellInfo(SpellIds.Blink, Difficulty.None); - unit.GetSpellHistory().ResetCharges(blink.ChargeCategoryId); - } - unit.CastSpell(unit, SpellIds.AlterTimeVisual); + SpellInfo blink = Global.SpellMgr.GetSpellInfo(SpellIds.Blink, Difficulty.None); + unit.GetSpellHistory().ResetCharges(blink.ChargeCategoryId); } - } - - public override void Register() - { - OnEffectApply.Add(new(OnApply, 0, AuraType.OverrideActionbarSpells, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.OverrideActionbarSpells, AuraEffectHandleModes.Real)); + unit.CastSpell(unit, SpellIds.AlterTimeVisual); } } - // 127140 - Alter Time Active - [Script] // 342247 - Alter Time Active - class spell_mage_alter_time_active : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AlterTimeAura, SpellIds.ArcaneAlterTimeAura); - } + OnEffectApply.Add(new(OnApply, 0, AuraType.OverrideActionbarSpells, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.OverrideActionbarSpells, AuraEffectHandleModes.Real)); + } +} - void RemoveAlterTimeAura(uint effIndex) - { - Unit unit = GetCaster(); - unit.RemoveAura(SpellIds.AlterTimeAura, ObjectGuid.Empty, 0, AuraRemoveMode.Expire); - unit.RemoveAura(SpellIds.ArcaneAlterTimeAura, ObjectGuid.Empty, 0, AuraRemoveMode.Expire); - } +// 127140 - Alter Time Active +[Script] // 342247 - Alter Time Active +class spell_mage_alter_time_active : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AlterTimeAura, SpellIds.ArcaneAlterTimeAura); + } - public override void Register() + void RemoveAlterTimeAura(uint effIndex) + { + Unit unit = GetCaster(); + unit.RemoveAura(SpellIds.AlterTimeAura, ObjectGuid.Empty, 0, AuraRemoveMode.Expire); + unit.RemoveAura(SpellIds.ArcaneAlterTimeAura, ObjectGuid.Empty, 0, AuraRemoveMode.Expire); + } + + public override void Register() + { + OnEffectHit.Add(new(RemoveAlterTimeAura, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 44425 - Arcane Barrage +class spell_mage_arcane_barrage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ArcaneBarrageR3, SpellIds.ArcaneBarrageEnergize) + && ValidateSpellEffect((spellInfo.Id, 1)); + } + + void ConsumeArcaneCharges() + { + Unit caster = GetCaster(); + + // Consume all arcane charges + int arcaneCharges = -caster.ModifyPower(PowerType.ArcaneCharges, -caster.GetMaxPower(PowerType.ArcaneCharges), false); + if (arcaneCharges != 0) { - OnEffectHit.Add(new(RemoveAlterTimeAura, 0, SpellEffectName.Dummy)); + AuraEffect auraEffect = caster.GetAuraEffect(SpellIds.ArcaneBarrageR3, 0, caster.GetGUID()); + if (auraEffect != null) + caster.CastSpell(caster, SpellIds.ArcaneBarrageEnergize, new CastSpellExtraArgs(SpellValueMod.BasePoint0, arcaneCharges * auraEffect.GetAmount() / 100)); } } - [Script] // 44425 - Arcane Barrage - class spell_mage_arcane_barrage : SpellScript + void HandleEffectHitTarget(uint effIndex) { - ObjectGuid _primaryTarget; + if (GetHitUnit().GetGUID() != _primaryTarget) + SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), GetEffectInfo(1).CalcValue(GetCaster()))); + } - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ArcaneBarrageR3, SpellIds.ArcaneBarrageEnergize) && ValidateSpellEffect((spellInfo.Id, 1)); - } + void MarkPrimaryTarget(uint effIndex) + { + _primaryTarget = GetHitUnit().GetGUID(); + } - void ConsumeArcaneCharges() + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage)); + OnEffectLaunchTarget.Add(new(MarkPrimaryTarget, 1, SpellEffectName.Dummy)); + AfterCast.Add(new(ConsumeArcaneCharges)); + } + + ObjectGuid _primaryTarget; +} + +[Script] // 195302 - Arcane Charge +class spell_mage_arcane_charge_clear : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ArcaneCharge); + } + + void RemoveArcaneCharge(uint effIndex) + { + GetHitUnit().RemoveAurasDueToSpell(SpellIds.ArcaneCharge); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(RemoveArcaneCharge, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 1449 - Arcane Explosion +class spell_mage_arcane_explosion : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + if (!ValidateSpellInfo(SpellIds.ArcaneMage, SpellIds.Reverberate)) + return false; + + if (!ValidateSpellEffect((spellInfo.Id, 1))) + return false; + + return spellInfo.GetEffect(1).IsEffect(SpellEffectName.SchoolDamage); + } + + void CheckRequiredAuraForBaselineEnergize(uint effIndex) + { + if (GetUnitTargetCountForEffect(1) == 0 || !GetCaster().HasAura(SpellIds.ArcaneMage)) + PreventHitDefaultEffect(effIndex); + } + + void HandleReverberate(uint effIndex) + { + bool procTriggered() { Unit caster = GetCaster(); - - // Consume all arcane charges - int arcaneCharges = -caster.ModifyPower(PowerType.ArcaneCharges, -caster.GetMaxPower(PowerType.ArcaneCharges), false); - if (arcaneCharges != 0) - { - AuraEffect auraEffect = caster.GetAuraEffect(SpellIds.ArcaneBarrageR3, 0, caster.GetGUID()); - if (auraEffect != null) - caster.CastSpell(caster, SpellIds.ArcaneBarrageEnergize, new CastSpellExtraArgs(SpellValueMod.BasePoint0, arcaneCharges * auraEffect.GetAmount() / 100)); - } - } - - void HandleEffectHitTarget(uint effIndex) - { - if (GetHitUnit().GetGUID() != _primaryTarget) - SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), GetEffectInfo(1).CalcValue(GetCaster()))); - } - - void MarkPrimaryTarget(uint effIndex) - { - _primaryTarget = GetHitUnit().GetGUID(); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage)); - OnEffectLaunchTarget.Add(new(MarkPrimaryTarget, 1, SpellEffectName.Dummy)); - AfterCast.Add(new(ConsumeArcaneCharges)); - } - } - - [Script] // 195302 - Arcane Charge - class spell_mage_arcane_charge_clear : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ArcaneCharge); - } - - void RemoveArcaneCharge(uint effIndex) - { - GetHitUnit().RemoveAurasDueToSpell(SpellIds.ArcaneCharge); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(RemoveArcaneCharge, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 1449 - Arcane Explosion - class spell_mage_arcane_explosion : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - if (!ValidateSpellInfo(SpellIds.ArcaneMage, SpellIds.Reverberate)) + AuraEffect triggerChance = caster.GetAuraEffect(SpellIds.Reverberate, 0); + if (triggerChance == null) return false; - if (!ValidateSpellEffect((spellInfo.Id, 1))) + AuraEffect requiredTargets = caster.GetAuraEffect(SpellIds.Reverberate, 1); + if (requiredTargets == null) return false; - return spellInfo.GetEffect(1).IsEffect(SpellEffectName.SchoolDamage); + return GetUnitTargetCountForEffect(1) >= requiredTargets.GetAmount() && RandomHelper.randChance(triggerChance.GetAmount()); } + ; - void CheckRequiredAuraForBaselineEnergize(uint effIndex) - { - if (GetUnitTargetCountForEffect(1) == 0 || !GetCaster().HasAura(SpellIds.ArcaneMage)) - PreventHitDefaultEffect(effIndex); - } - - void HandleReverberate(uint effIndex) - { - bool procTriggered() - { - Unit caster = GetCaster(); - AuraEffect triggerChance = caster.GetAuraEffect(SpellIds.Reverberate, 0); - if (triggerChance == null) - return false; - - AuraEffect requiredTargets = caster.GetAuraEffect(SpellIds.Reverberate, 1); - if (requiredTargets == null) - return false; - - return GetUnitTargetCountForEffect(1) >= requiredTargets.GetAmount() && RandomHelper.randChance(triggerChance.GetAmount()); - } - - if (!procTriggered()) - PreventHitDefaultEffect(effIndex); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(CheckRequiredAuraForBaselineEnergize, 0, SpellEffectName.Energize)); - OnEffectHitTarget.Add(new(HandleReverberate, 2, SpellEffectName.Energize)); - } + if (!procTriggered()) + PreventHitDefaultEffect(effIndex); } - [Script] // 235313 - Blazing Barrier - class spell_mage_blazing_barrier : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlazingBarrierTrigger); - } + OnEffectHitTarget.Add(new(CheckRequiredAuraForBaselineEnergize, 0, SpellEffectName.Energize)); + OnEffectHitTarget.Add(new(HandleReverberate, 2, SpellEffectName.Energize)); + } +} - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) +[Script] // 235313 - Blazing Barrier +class spell_mage_blazing_barrier : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlazingBarrierTrigger); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = false; + Unit caster = GetCaster(); + if (caster != null) + amount = (int)(caster.SpellBaseHealingBonusDone(GetSpellInfo().GetSchoolMask()) * 7.0f); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit caster = eventInfo.GetDamageInfo().GetVictim(); + Unit target = eventInfo.GetDamageInfo().GetAttacker(); + + if (caster != null && target != null) + caster.CastSpell(target, SpellIds.BlazingBarrierTrigger, true); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + OnEffectProc.Add(new(HandleProc, 1, AuraType.ProcTriggerSpell)); + } +} + +// 190356 - Blizzard +[Script] // 4658 - AreaTrigger Create Properties +class areatrigger_mage_blizzard(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + static TimeSpan TickPeriod = TimeSpan.FromSeconds(1000); + + TimeSpan _tickTimer = TickPeriod; + + public override void OnUpdate(uint diff) + { + _tickTimer -= TimeSpan.FromSeconds(diff); + + while (_tickTimer <= TimeSpan.Zero) { - canBeRecalculated = false; - Unit caster = GetCaster(); + Unit caster = at.GetCaster(); if (caster != null) - amount = (int)(caster.SpellBaseHealingBonusDone(GetSpellInfo().GetSchoolMask()) * 7.0f); - } + caster.CastSpell(at.GetPosition(), SpellIds.BlizzardDamage); - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetDamageInfo().GetVictim(); - Unit target = eventInfo.GetDamageInfo().GetAttacker(); - - if (caster != null && target != null) - caster.CastSpell(target, SpellIds.BlazingBarrierTrigger, true); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); - OnEffectProc.Add(new(HandleProc, 1, AuraType.ProcTriggerSpell)); + _tickTimer += TickPeriod; } } +} - // 190356 - Blizzard - [Script] // 4658 - AreaTrigger Create Properties - class areatrigger_mage_blizzard : AreaTriggerAI +[Script] // 190357 - Blizzard (Damage) +class spell_mage_blizzard_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - TimeSpan TickPeriod = TimeSpan.FromMilliseconds(1000); - - TimeSpan _tickTimer; - - public areatrigger_mage_blizzard(AreaTrigger areatrigger) : base(areatrigger) - { - _tickTimer = TickPeriod; - } - - public override void OnUpdate(uint diff) - { - _tickTimer -= TimeSpan.FromMilliseconds(diff); - - while (_tickTimer <= TimeSpan.FromSeconds(0)) - { - Unit caster = at.GetCaster(); - if (caster != null) - caster.CastSpell(at.GetPosition(), SpellIds.BlizzardDamage); - - _tickTimer += TickPeriod; - } - } + return ValidateSpellInfo(SpellIds.BlizzardSlow); } - [Script] // 190357 - Blizzard (Damage) - class spell_mage_blizzard_damage : SpellScript + void HandleSlow(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlizzardSlow); - } - - void HandleSlow(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.BlizzardSlow, TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleSlow, 0, SpellEffectName.SchoolDamage)); - } + GetCaster().CastSpell(GetHitUnit(), SpellIds.BlizzardSlow, TriggerCastFlags.IgnoreCastInProgress); } - [Script] // 198063 - Burning Determination - class spell_mage_burning_determination : AuraScript + public override void Register() { - bool CheckProc(ProcEventInfo eventInfo) - { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo != null && (spellInfo.GetAllEffectsMechanicMask() & ((1 << (int)Mechanics.Interrupt) | (1 << (int)Mechanics.Silence))) != 0) + OnEffectHitTarget.Add(new(HandleSlow, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 198063 - Burning Determination +class spell_mage_burning_determination : AuraScript +{ + bool CheckProc(ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo != null) + if ((spellInfo.GetAllEffectsMechanicMask() & ((1 << (int)Mechanics.Interrupt) | (1 << (int)Mechanics.Silence))) != 0) return true; - return false; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - } + return false; } - [Script] // 86949 - Cauterize - class spell_mage_cauterize : SpellScript + public override void Register() { - void SuppressSpeedBuff(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - } + DoCheckProc.Add(new(CheckProc)); + } +} - public override void Register() - { - OnEffectLaunch.Add(new(SuppressSpeedBuff, 2, SpellEffectName.TriggerSpell)); - } +[Script] // 86949 - Cauterize +class spell_mage_cauterize : SpellScript +{ + void SuppressSpeedBuff(uint effIndex) + { + PreventHitDefaultEffect(effIndex); } - [Script] - class spell_mage_cauterize_AuraScript : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 2)) && ValidateSpellInfo(SpellIds.CauterizeDot, SpellIds.Cauterized, spellInfo.GetEffect(2).TriggerSpell); - } + OnEffectLaunch.Add(new(SuppressSpeedBuff, 2, SpellEffectName.TriggerSpell)); + } +} - void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - AuraEffect effect1 = GetEffect(1); - if (effect1 == null || - !GetTargetApplication().HasEffect(1) || - dmgInfo.GetDamage() < GetTarget().GetHealth() || - dmgInfo.GetDamage() > GetTarget().GetMaxHealth() * 2 || - GetTarget().HasAura(SpellIds.Cauterized)) - { - PreventDefaultAction(); - return; - } - - GetTarget().SetHealth(GetTarget().CountPctFromMaxHealth(effect1.GetAmount())); - GetTarget().CastSpell(GetTarget(), GetEffectInfo(2).TriggerSpell, TriggerCastFlags.FullMask); - GetTarget().CastSpell(GetTarget(), SpellIds.CauterizeDot, TriggerCastFlags.FullMask); - GetTarget().CastSpell(GetTarget(), SpellIds.Cauterized, TriggerCastFlags.FullMask); - } - - public override void Register() - { - OnEffectAbsorb.Add(new(HandleAbsorb, 0)); - } +[Script] +class spell_mage_cauterize_AuraScript : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 2)) && ValidateSpellInfo + (SpellIds.CauterizeDot, SpellIds.Cauterized, spellInfo.GetEffect(2).TriggerSpell); } - [Script] // 235219 - Cold Snap - class spell_mage_cold_snap : SpellScript + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) { - uint[] SpellsToReset = + AuraEffect aura = GetEffect(1); + if (aura == null || + !GetTargetApplication().HasEffect(1) || + dmgInfo.GetDamage() < GetTarget().GetHealth() || + dmgInfo.GetDamage() > GetTarget().GetMaxHealth() * 2 || + GetTarget().HasAura(SpellIds.Cauterized)) { - SpellIds.ConeOfCold, - SpellIds.IceBarrier, - SpellIds.IceBlock, - }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellsToReset) && ValidateSpellInfo(SpellIds.FrostNova); + PreventDefaultAction(); + return; } - void HandleDummy(uint effIndex) - { - foreach (uint spellId in SpellsToReset) - GetCaster().GetSpellHistory().ResetCooldown(spellId, true); - - GetCaster().GetSpellHistory().RestoreCharge(SpellMgr.GetSpellInfo(SpellIds.FrostNova, GetCastDifficulty()).ChargeCategoryId); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); - } + GetTarget().SetHealth(GetTarget().CountPctFromMaxHealth(aura.GetAmount())); + GetTarget().CastSpell(GetTarget(), GetEffectInfo(2).TriggerSpell, TriggerCastFlags.FullMask); + GetTarget().CastSpell(GetTarget(), SpellIds.CauterizeDot, TriggerCastFlags.FullMask); + GetTarget().CastSpell(GetTarget(), SpellIds.Cauterized, TriggerCastFlags.FullMask); } - class CometStormEvent : BasicEvent + public override void Register() + { + OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + } +} + +[Script] // 235219 - Cold Snap +class spell_mage_cold_snap : SpellScript +{ + static uint[] SpellsToReset = [SpellIds.ConeOfCold, SpellIds.IceBarrier, SpellIds.IceBlock,]; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellsToReset) && ValidateSpellInfo(SpellIds.FrostNova); + } + + void HandleDummy(uint effIndex) + { + foreach (uint spellId in SpellsToReset) + GetCaster().GetSpellHistory().ResetCooldown(spellId, true); + + GetCaster().GetSpellHistory().RestoreCharge(Global.SpellMgr.GetSpellInfo(SpellIds.FrostNova, GetCastDifficulty()).ChargeCategoryId); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 153595 - Comet Storm (launch) +class spell_mage_comet_storm : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CometStormVisual); + } + + void EffectHit(uint effIndex) + { + GetCaster().m_Events.AddEventAtOffset(new CometStormEvent(GetCaster(), GetSpell().m_castId, GetHitDest()), RandomHelper.RandTime(TimeSpan.FromSeconds(100), TimeSpan.FromSeconds(275))); + } + + public override void Register() + { + OnEffectHit.Add(new(EffectHit, 0, SpellEffectName.Dummy)); + } + + class CometStormEvent(Unit caster, ObjectGuid originalCastId, Position dest) : BasicEvent { - Unit _caster; - ObjectGuid _originalCastId; - Position _dest; byte _count; - public CometStormEvent(Unit caster, ObjectGuid originalCastId, Position dest) - { - _caster = caster; - _originalCastId = originalCastId; - _dest = dest; - } - public override bool Execute(ulong time, uint diff) { - Position destPosition = new(_dest.GetPositionX() + RandomHelper.FRand(-3.0f, 3.0f), _dest.GetPositionY() + RandomHelper.FRand(-3.0f, 3.0f), _dest.GetPositionZ()); - _caster.CastSpell(destPosition, SpellIds.CometStormVisual, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetOriginalCastId(_originalCastId)); + Position destPosition = new(dest.GetPositionX() + RandomHelper.FRand(-3.0f, 3.0f), dest.GetPositionY() + RandomHelper.FRand(-3.0f, 3.0f), dest.GetPositionZ()); + caster.CastSpell(destPosition, SpellIds.CometStormVisual, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetOriginalCastId(originalCastId)); ++_count; if (_count >= 7) return true; - _caster.m_Events.AddEvent(this, TimeSpan.FromMilliseconds(time) + RandomHelper.RandTime(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(275))); + caster.m_Events.AddEvent(this, TimeSpan.FromSeconds(time) + RandomHelper.RandTime(TimeSpan.FromSeconds(100), TimeSpan.FromSeconds(275))); + return false; + } + } +} + +[Script] // 228601 - Comet Storm (damage) +class spell_mage_comet_storm_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CometStormDamage); + } + + void HandleEffectHitTarget(uint effIndex) + { + GetCaster().CastSpell(GetHitDest(), SpellIds.CometStormDamage, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetOriginalCastId(GetSpell().m_originalCastId)); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 120 - Cone of Cold +class spell_mage_cone_of_cold : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ConeOfColdSlow); + } + + void HandleSlow(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ConeOfColdSlow, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleSlow, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 190336 - Conjure Refreshment +class spell_mage_conjure_refreshment : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ConjureRefreshment, SpellIds.ConjureRefreshmentTable); + } + + void HandleDummy(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + if (caster != null) + { + Group group = caster.GetGroup(); + if (group != null) + caster.CastSpell(caster, SpellIds.ConjureRefreshmentTable, true); + else + caster.CastSpell(caster, SpellIds.ConjureRefreshment, true); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 410939 - Ethereal Blink +class spell_mage_ethereal_blink : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Blink, SpellIds.Shimmer); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + PreventDefaultAction(); + + // this proc only works for players because teleport relocation happens after an Ack + GetTarget().CastSpell(procInfo.GetProcSpell().m_targets.GetDst(), aurEff.GetSpellEffectInfo().TriggerSpell, new CastSpellExtraArgs(aurEff) + .SetTriggeringSpell(procInfo.GetProcSpell()) + .SetCustomArg(GetTarget().GetPosition())); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 410941 - Ethereal Blink +class spell_mage_ethereal_blink_triggered : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Blink, SpellIds.Shimmer, SpellIds.Slow) + && ValidateSpellEffect((SpellIds.EtherealBlink, 3)); + } + + void FilterTargets(List targets) + { + Position src = (Position)GetSpell().m_customArg; + WorldLocation dst = GetExplTargetDest(); + if (src == null || dst == null) + { + targets.Clear(); + return; + } + + targets.RemoveAll(target => !target.IsInBetween(src, dst, (target.GetCombatReach() + GetCaster().GetCombatReach()) / 2.0f)); + + AuraEffect reductionEffect = GetCaster().GetAuraEffect(SpellIds.EtherealBlink, 2); + if (reductionEffect == null) + return; + + TimeSpan reduction = TimeSpan.FromSeconds(reductionEffect.GetAmount()) * targets.Count; + + AuraEffect cap = GetCaster().GetAuraEffect(SpellIds.EtherealBlink, 3); + if (cap != null) + if (reduction > TimeSpan.FromSeconds(cap.GetAmount())) + reduction = TimeSpan.FromSeconds(cap.GetAmount()); + + if (reduction > TimeSpan.Zero) + { + GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.Blink, -reduction); + GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.Shimmer, -reduction); + } + } + + void TriggerSlow(uint effIndex) + { + int effectivenessPct = 100; + AuraEffect effectivenessEffect = GetCaster().GetAuraEffect(SpellIds.EtherealBlink, 1); + if (effectivenessEffect != null) + effectivenessPct = effectivenessEffect.GetAmount(); + + int slowPct = Global.SpellMgr.GetSpellInfo(SpellIds.Slow, Difficulty.None).GetEffect(0).CalcBaseValue(GetCaster(), GetHitUnit(), 0, -1); + MathFunctions.ApplyPct(ref slowPct, effectivenessPct); + + GetCaster().CastSpell(GetHitUnit(), SpellIds.Slow, new CastSpellExtraArgs(GetSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, slowPct)); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(TriggerSlow, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 383395 - Feel the Burn +class spell_mage_feel_the_burn : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FeelTheBurn); + } + + void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Unit caster = GetCaster(); + if (caster != null) + { + AuraEffect valueHolder = caster.GetAuraEffect(SpellIds.FeelTheBurn, 0); + if (valueHolder != null) + amount = valueHolder.GetAmount(); + } + + canBeRecalculated = false; + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalcAmount, 0, AuraType.Mastery)); + } +} + +[Script] // 112965 - Fingers of Frost +class spell_mage_fingers_of_frost : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FingersOfFrost); + } + + bool CheckFrostboltProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Mage, new FlagArray128(0, 0x2000000, 0, 0)) + && RandomHelper.randChance(aurEff.GetAmount()); + } + + bool CheckFrozenOrbProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Mage, new FlagArray128(0, 0, 0x80, 0)) + && RandomHelper.randChance(aurEff.GetAmount()); + } + + void Trigger(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(GetTarget(), SpellIds.FingersOfFrost, aurEff); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckFrostboltProc, 0, AuraType.Dummy)); + DoCheckEffectProc.Add(new(CheckFrozenOrbProc, 1, AuraType.Dummy)); + AfterEffectProc.Add(new(Trigger, 0, AuraType.Dummy)); + AfterEffectProc.Add(new(Trigger, 1, AuraType.Dummy)); + } +} + +// 133 - Fireball +[Script] // 11366 - Pyroblast +class spell_mage_firestarter : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Firestarter); + } + + void CalcCritChance(Unit victim, ref float critChance) + { + AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.Firestarter, 0); + if (aurEff != null) + if (victim.GetHealthPct() >= aurEff.GetAmount()) + critChance = 100.0f; + } + + public override void Register() + { + OnCalcCritChance.Add(new(CalcCritChance)); + } +} + +[Script] // 321712 - Pyroblast +class spell_mage_firestarter_dots : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Firestarter); + } + + void CalcCritChance(AuraEffect aurEff, Unit victim, ref float critChance) + { + AuraEffect aurEff1 = GetCaster().GetAuraEffect(SpellIds.Firestarter, 0); + if (aurEff1 != null) + if (victim.GetHealthPct() >= aurEff1.GetAmount()) + critChance = 100.0f; + } + + public override void Register() + { + DoEffectCalcCritChance.Add(new(CalcCritChance, SpellConst.EffectAll, AuraType.PeriodicDamage)); + } +} + +[Script] // 108853 - Fire Blast +class spell_mage_fire_blast : SpellScript +{ + void CalcCritChance(Unit victim, ref float critChance) + { + critChance = 100.0f; + } + + public override void Register() + { + OnCalcCritChance.Add(new(CalcCritChance)); + } +} + +[Script] // 205029 - Flame On +class spell_mage_flame_on : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FireBlast) + && CliDB.SpellCategoryStorage.HasRecord(Global.SpellMgr.GetSpellInfo(SpellIds.FireBlast, Difficulty.None).ChargeCategoryId) + && ValidateSpellEffect((spellInfo.Id, 2)); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = false; + amount = (int)(-MathFunctions.GetPctOf(GetEffectInfo(2).CalcValue() * Time.InMilliseconds, CliDB.SpellCategoryStorage.LookupByKey(Global.SpellMgr.GetSpellInfo(SpellIds.FireBlast, Difficulty.None).ChargeCategoryId).ChargeRecoveryTime)); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ChargeRecoveryMultiplier)); + } +} + +[Script] // 205037 - Flame Patch (attached to 2120 - Flamestrike) +class spell_mage_flame_patch : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlamePatchTalent, SpellIds.FlamePatchAreatrigger); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.FlamePatchTalent); + } + + void HandleFlamePatch() + { + GetCaster().CastSpell(GetExplTargetDest().GetPosition(), SpellIds.FlamePatchAreatrigger, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleFlamePatch)); + } +} + +// 205470 - Flame Patch +[Script] // Id - 6122 +class at_mage_flame_patch(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TaskScheduler _scheduler = new(); + + public override void OnCreate(Spell creatingSpell) + { + _scheduler.Schedule(TimeSpan.FromSeconds(1), task => + { + Unit caster = at.GetCaster(); + if (caster != null) + caster.CastSpell(at.GetPosition(), SpellIds.FlamePatchDamage, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + + task.Repeat(); + }); + } + + public override void OnUpdate(uint diff) + { + _scheduler.Update(diff); + } +} + +[Script] // 44614 - Flurry +class spell_mage_flurry : SpellScript +{ + class FlurryEvent(Unit caster, ObjectGuid target, ObjectGuid originalCastId, int count) : BasicEvent + { + public override bool Execute(ulong time, uint diff) + { + Unit target1 = Global.ObjAccessor.GetUnit(caster, target); + if (target1 == null) + return true; + + caster.CastSpell(target1, SpellIds.FlurryDamage, new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetOriginalCastId(originalCastId)); + + if (--count == 0) + return true; + + caster.m_Events.AddEvent(this, TimeSpan.FromSeconds(time) + RandomHelper.RandTime(TimeSpan.FromSeconds(300), TimeSpan.FromSeconds(400))); return false; } } - [Script] // 153595 - Comet Storm (launch) - class spell_mage_comet_storm : SpellScript + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CometStormVisual); - } - - void EffectHit(uint effIndex) - { - GetCaster().m_Events.AddEventAtOffset(new CometStormEvent(GetCaster(), GetSpell().m_castId, GetHitDest()), RandomHelper.RandTime(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(275))); - } - - public override void Register() - { - OnEffectHit.Add(new(EffectHit, 0, SpellEffectName.Dummy)); - } + return ValidateSpellInfo(SpellIds.FlurryDamage); } - [Script] // 228601 - Comet Storm (damage) - class spell_mage_comet_storm_damage : SpellScript + void EffectHit(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CometStormDamage); - } - - void HandleEffectHitTarget(uint effIndex) - { - GetCaster().CastSpell(GetHitDest(), SpellIds.CometStormDamage, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetOriginalCastId(GetSpell().m_originalCastId)); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); - } + GetCaster().m_Events.AddEventAtOffset(new FlurryEvent(GetCaster(), GetHitUnit().GetGUID(), GetSpell().m_castId, GetEffectValue() - 1), RandomHelper.RandTime(TimeSpan.FromSeconds(300), TimeSpan.FromSeconds(400))); } - [Script] // 120 - Cone of Cold - class spell_mage_cone_of_cold : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ConeOfColdSlow); - } + OnEffectHitTarget.Add(new(EffectHit, 0, SpellEffectName.Dummy)); + } +} - void HandleSlow(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.ConeOfColdSlow, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleSlow, 0, SpellEffectName.SchoolDamage)); - } +[Script] // 228354 - Flurry (damage) +class spell_mage_flurry_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.WintersChill); } - [Script] // 190336 - Conjure Refreshment - class spell_mage_conjure_refreshment : SpellScript + void HandleDamage(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ConjureRefreshment, SpellIds.ConjureRefreshmentTable); - } + GetCaster().CastSpell(GetHitUnit(), SpellIds.WintersChill, true); + } - void HandleDummy(uint effIndex) + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDamage, 1, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 116 - Frostbolt +class spell_mage_frostbolt : SpellScript +{ + public override bool Validate(SpellInfo spell) + { + return ValidateSpellInfo(SpellIds.Chilled); + } + + void HandleChilled() + { + Unit target = GetHitUnit(); + if (target != null) + GetCaster().CastSpell(target, SpellIds.Chilled, TriggerCastFlags.IgnoreCastInProgress); + } + + public override void Register() + { + OnHit.Add(new(HandleChilled)); + } +} + +[Script] // 386737 - Hyper Impact +class spell_mage_hyper_impact : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Supernova); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.Supernova, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 11426 - Ice Barrier +class spell_mage_ice_barrier : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Chilled); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = false; + amount = (int)MathFunctions.CalculatePct(GetUnitOwner().GetMaxHealth(), GetEffectInfo(1).CalcValue()); + Player player = GetUnitOwner().ToPlayer(); + if (player != null) + MathFunctions.AddPct(ref amount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone) + player.GetTotalAuraModifier(AuraType.ModVersatility)); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = eventInfo.GetDamageInfo().GetVictim(); + Unit target = eventInfo.GetDamageInfo().GetAttacker(); + + if (caster != null && target != null) + caster.CastSpell(target, SpellIds.Chilled, true); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.SchoolAbsorb)); + } +} + +[Script] // 45438 - Ice Block +class spell_mage_ice_block : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EverwarmSocks); + } + + void PreventStunWithEverwarmSocks(ref WorldObject target) + { + if (GetCaster().HasAura(SpellIds.EverwarmSocks)) + target = null; + } + + void PreventEverwarmSocks(ref WorldObject target) + { + if (!GetCaster().HasAura(SpellIds.EverwarmSocks)) + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(PreventStunWithEverwarmSocks, 0, Targets.UnitCaster)); + OnObjectTargetSelect.Add(new(PreventEverwarmSocks, 5, Targets.UnitCaster)); + OnObjectTargetSelect.Add(new(PreventEverwarmSocks, 6, Targets.UnitCaster)); + } +} + +[Script] // Ice Lance - 30455 +class spell_mage_ice_lance : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IceLanceTrigger, SpellIds.ThermalVoid, SpellIds.IcyVeins, SpellIds.ChainReactionDummy, SpellIds.ChainReaction, SpellIds.FingersOfFrost); + } + + void IndexTarget(uint effIndex) + { + _orderedTargets.Add(GetHitUnit().GetGUID()); + } + + void HandleOnHit(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + int index = _orderedTargets.IndexOf(target.GetGUID()); + + if (index == 0 // only primary target triggers these benefits + && target.HasAuraState(AuraStateType.Frozen, GetSpellInfo(), caster)) { - Player caster = GetCaster().ToPlayer(); - if (caster != null) + // Thermal Void + Aura thermalVoid = caster.GetAura(SpellIds.ThermalVoid); + if (thermalVoid != null && !thermalVoid.GetSpellInfo().GetEffects().Empty()) { - Group group = caster.GetGroup(); - if (group != null) - caster.CastSpell(caster, SpellIds.ConjureRefreshmentTable, true); - else - caster.CastSpell(caster, SpellIds.ConjureRefreshment, true); + Aura icyVeins = caster.GetAura(SpellIds.IcyVeins); + if (icyVeins != null) + icyVeins.SetDuration(icyVeins.GetDuration() + thermalVoid.GetSpellInfo().GetEffect(0).CalcValue(caster) * Time.InMilliseconds); } + + // Chain Reaction + if (caster.HasAura(SpellIds.ChainReactionDummy)) + caster.CastSpell(caster, SpellIds.ChainReaction, true); } - public override void Register() + // put target index for chain value multiplier into 1 base points, otherwise triggered spell doesn't know which damage multiplier to apply + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.BasePoint1, index); + caster.CastSpell(target, SpellIds.IceLanceTrigger, args); + } + + public override void Register() + { + OnEffectLaunchTarget.Add(new(IndexTarget, 0, SpellEffectName.ScriptEffect)); + OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.ScriptEffect)); + } + + List _orderedTargets; +} + +[Script] // 228598 - Ice Lance +class spell_mage_ice_lance_damage : SpellScript +{ + void ApplyDamageMultiplier(uint effIndex) + { + SpellValue spellValue = GetSpellValue(); + if ((spellValue.CustomBasePointsMask & (1 << 1)) != 0) { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + int originalDamage = GetHitDamage(); + float targetIndex = (float)spellValue.EffectBasePoints[1]; + float multiplier = MathF.Pow(GetEffectInfo().CalcDamageMultiplier(GetCaster(), GetSpell()), targetIndex); + SetHitDamage((int)(originalDamage * multiplier)); } } - [Script] // 410939 - Ethereal Blink - class spell_mage_ethereal_blink : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Blink, SpellIds.Shimmer); - } + OnEffectHitTarget.Add(new(ApplyDamageMultiplier, 0, SpellEffectName.SchoolDamage)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) +[Script] // 12846 - Ignite +class spell_mage_ignite : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Ignite); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() != null; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + SpellInfo igniteDot = Global.SpellMgr.GetSpellInfo(SpellIds.Ignite, GetCastDifficulty()); + int pct = aurEff.GetAmount(); + + Cypher.Assert(igniteDot.GetMaxTicks() > 0); + int amount = (int)(MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), pct) / igniteDot.GetMaxTicks()); + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, amount); + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.Ignite, args); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// 37447 - Improved Mana Gems +[Script] // 61062 - Improved Mana Gems +class spell_mage_imp_mana_gems : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ManaSurge); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + eventInfo.GetActor().CastSpell(null, SpellIds.ManaSurge, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 383967 - Improved Combustion (attached to 190319 - Combustion) +class spell_mage_improved_combustion : AuraScript +{ + public override bool Load() + { + return GetUnitOwner().HasAura(SpellIds.ImprovedCombustion); + } + + void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + AuraEffect amountHolder = GetEffect(2); + if (amountHolder != null) + { + int critRating = (int)GetUnitOwner().ToPlayer().m_activePlayerData.CombatRatings[(int)CombatRating.CritSpell]; + amount = MathFunctions.CalculatePct(critRating, amountHolder.GetAmount()); + } + } + + void UpdatePeriodic(AuraEffect aurEff) + { + AuraEffect bonus = GetEffect(1); + if (bonus != null) + bonus.RecalculateAmount(aurEff); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalcAmount, 1, AuraType.ModRating)); + OnEffectPeriodic.Add(new(UpdatePeriodic, 2, AuraType.PeriodicDummy)); + } +} + +[Script] // 383604 - Improved Scorch +class spell_mage_improved_scorch : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImprovedScorch); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget().HealthBelowPct(aurEff.GetAmount()); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.ImprovedScorch, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 1463 - Incanter's Flow +class spell_mage_incanters_flow : AuraScript +{ + sbyte modifier = 1; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IncantersFlow); + } + + void HandlePeriodicTick(AuraEffect aurEff) + { + // Incanter's flow should not cycle out of combat + if (!GetTarget().IsInCombat()) + return; + + Aura aura = GetTarget().GetAura(SpellIds.IncantersFlow); + if (aura != null) + { + uint stacks = aura.GetStackAmount(); + + // Force always to values between 1 and 5 + if ((modifier == -1 && stacks == 1) || (modifier == 1 && stacks == 5)) + { + modifier *= -1; + return; + } + + aura.ModStackAmount(modifier); + } + else + GetTarget().CastSpell(GetTarget(), SpellIds.IncantersFlow, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodicTick, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 44457 - Living Bomb +class spell_mage_living_bomb : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LivingBombPeriodic); + } + + void HandleDummy(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster().CastSpell(GetHitUnit(), SpellIds.LivingBombPeriodic, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint2, 1)); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 44461 - Living Bomb +class spell_mage_living_bomb_explosion : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return spellInfo.NeedsExplicitUnitTarget() && ValidateSpellInfo(SpellIds.LivingBombPeriodic); + } + + void FilterTargets(List targets) + { + targets.Remove(GetExplTargetWorldObject()); + } + + void HandleSpread(uint effIndex) + { + if (GetSpellValue().EffectBasePoints[0] > 0) + GetCaster().CastSpell(GetHitUnit(), SpellIds.LivingBombPeriodic, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint2, 0)); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(HandleSpread, 1, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 217694 - Living Bomb +class spell_mage_living_bomb_periodic : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LivingBombExplosion); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.LivingBombExplosion, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount())); + } + + public override void Register() + { + AfterEffectRemove.Add(new(AfterRemove, 2, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 153561 - Meteor +class spell_mage_meteor : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MeteorAreatrigger); + } + + void EffectHit(uint effIndex) + { + GetCaster().CastSpell(GetHitDest(), SpellIds.MeteorAreatrigger, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHit.Add(new(EffectHit, 0, SpellEffectName.Dummy)); + } +} + +// 177345 - Meteor +[Script] // Id - 3467 +class at_mage_meteor(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnRemove() + { + Unit caster = at.GetCaster(); + if (caster != null) + caster.CastSpell(at.GetPosition(), SpellIds.MeteorMissile); + } +} + +// 175396 - Meteor Burn +[Script] // Id - 1712 +class at_mage_meteor_burn(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, SpellIds.MeteorBurnDamage, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + + public override void OnUnitExit(Unit unit) + { + unit.RemoveAurasDueToSpell(SpellIds.MeteorBurnDamage, at.GetCasterGUID()); + } +} + +[Script] // 457803 - Molten Fury +class spell_mage_molten_fury : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MoltenFury); + } + + static void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + if (!eventInfo.GetActionTarget().HealthAbovePct(aurEff.GetAmount())) + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.MoltenFury, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + else + eventInfo.GetActionTarget().RemoveAurasDueToSpell(SpellIds.MoltenFury, eventInfo.GetActor().GetGUID()); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +/// @todo move out of here and rename - not a mage spell +[Script] // 32826 - Polymorph (Visual) +class spell_mage_polymorph_visual : SpellScript +{ + const uint NpcAurosalia = 18744; + + uint[] PolymorhForms = + [ + SpellIds.SquirrelForm, + SpellIds.GiraffeForm, + SpellIds.SerpentForm, + SpellIds.DragonhawkForm, + SpellIds.WorgenForm, + SpellIds.SheepForm + ]; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(PolymorhForms); + } + + void HandleDummy(uint effIndex) + { + Unit target = GetCaster().FindNearestCreature(NpcAurosalia, 30.0f); + if (target != null) + if (target.IsTypeId(TypeId.Unit)) + target.CastSpell(target, PolymorhForms[RandomHelper.IRand(0, 5)], true); + } + + public override void Register() + { + // add dummy effect spell handler to Polymorph visual + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 235450 - Prismatic Barrier +class spell_mage_prismatic_barrier : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 5)); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = false; + Unit caster = GetCaster(); + if (caster != null) + amount = (int)MathFunctions.CalculatePct(caster.GetMaxHealth(), GetEffectInfo(5).CalcValue(caster)); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + } +} + +[Script] // 376103 - Radiant Spark +class spell_mage_radiant_spark : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RadiantSparkProcBlocker); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + return !procInfo.GetProcTarget().HasAura(SpellIds.RadiantSparkProcBlocker, GetCasterGUID()); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Aura vulnerability = procInfo.GetProcTarget().GetAura(aurEff.GetSpellEffectInfo().TriggerSpell, GetCasterGUID()); + if (vulnerability != null && vulnerability.GetStackAmount() == vulnerability.CalcMaxStackAmount()) { PreventDefaultAction(); - - // this proc only works for players because teleport relocation happens after an Ack - GetTarget().CastSpell(procInfo.GetProcSpell().m_targets.GetDst(), aurEff.GetSpellEffectInfo().TriggerSpell, new CastSpellExtraArgs(aurEff) - .SetTriggeringSpell(procInfo.GetProcSpell()) - .SetCustomArg(GetTarget().GetPosition())); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 1, AuraType.ProcTriggerSpell)); + vulnerability.Remove(); + GetTarget().CastSpell(GetTarget(), SpellIds.RadiantSparkProcBlocker, true); } } - [Script] // 410941 - Ethereal Blink - class spell_mage_ethereal_blink_triggered : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnEffectProc.Add(new(HandleProc, 2, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 205021 - Ray of Frost +class spell_mage_ray_of_frost : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RayOfFrostFingersOfFrost); + } + + void HandleOnHit() + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.RayOfFrostFingersOfFrost, TriggerCastFlags.IgnoreCastInProgress); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] +class spell_mage_ray_of_frost_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RayOfFrostBonus, SpellIds.RayOfFrostFingersOfFrost); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) { - return ValidateSpellInfo(SpellIds.Blink, SpellIds.Shimmer, SpellIds.Slow) && ValidateSpellEffect((SpellIds.EtherealBlink, 3)); - } - - void FilterTargets(List targets) - { - Position src = (Position)GetSpell().m_customArg; - WorldLocation dst = GetExplTargetDest(); - if (src == null || dst == null) - { - targets.Clear(); - return; - } - - targets.RemoveAll(target => !target.IsInBetween(src, dst, (target.GetCombatReach() + GetCaster().GetCombatReach()) / 2.0f)); - - AuraEffect reductionEffect = GetCaster().GetAuraEffect(SpellIds.EtherealBlink, 2); - if (reductionEffect == null) - return; - - TimeSpan reduction = TimeSpan.FromSeconds(reductionEffect.GetAmount()) * targets.Count; - - AuraEffect cap = GetCaster().GetAuraEffect(SpellIds.EtherealBlink, 3); - if (cap != null) - if (reduction > TimeSpan.FromSeconds(cap.GetAmount())) - reduction = TimeSpan.FromSeconds(cap.GetAmount()); - - if (reduction > TimeSpan.FromSeconds(0)) - { - GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.Blink, -reduction); - GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.Shimmer, -reduction); - } - } - - void TriggerSlow(uint effIndex) - { - int effectivenessPct = 100; - AuraEffect effectivenessEffect = GetCaster().GetAuraEffect(SpellIds.EtherealBlink, 1); - if (effectivenessEffect != null) - effectivenessPct = effectivenessEffect.GetAmount(); - - int slowPct = SpellMgr.GetSpellInfo(SpellIds.Slow, Difficulty.None).GetEffect(0).CalcBaseValue(GetCaster(), GetHitUnit(), 0, -1); - MathFunctions.ApplyPct(ref slowPct, effectivenessPct); - - GetCaster().CastSpell(GetHitUnit(), SpellIds.Slow, new CastSpellExtraArgs(GetSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, slowPct)); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(TriggerSlow, 0, SpellEffectName.Dummy)); + if (aurEff.GetTickNumber() > 1) // First tick should deal base damage + caster.CastSpell(caster, SpellIds.RayOfFrostBonus, true); } } - [Script] // 383395 - Feel the Burn - class spell_mage_feel_the_burn : AuraScript + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FeelTheBurn); - } - - void CalcAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit caster = GetCaster(); - if (caster != null) - { - AuraEffect valueHolder = caster.GetAuraEffect(SpellIds.FeelTheBurn, 0); - if (valueHolder != null) - amount = valueHolder.GetAmount(); - } - - canBeRecalculated = false; - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalcAmount, 0, AuraType.Mastery)); - } + Unit caster = GetCaster(); + if (caster != null) + caster.RemoveAurasDueToSpell(SpellIds.RayOfFrostFingersOfFrost); } - [Script] // 112965 - Fingers of Frost - class spell_mage_fingers_of_frost : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FingersOfFrost); - } - - bool CheckFrostboltProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Mage, new FlagArray128(0, 0x2000000, 0, 0)) - && RandomHelper.randChance(aurEff.GetAmount()); - } - - bool CheckFrozenOrbProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Mage, new FlagArray128(0, 0, 0x80, 0)) - && RandomHelper.randChance(aurEff.GetAmount()); - } - - void Trigger(AuraEffect aurEff, ProcEventInfo eventInfo) - { - eventInfo.GetActor().CastSpell(GetTarget(), SpellIds.FingersOfFrost, aurEff); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckFrostboltProc, 0, AuraType.Dummy)); - DoCheckEffectProc.Add(new(CheckFrozenOrbProc, 1, AuraType.Dummy)); - AfterEffectProc.Add(new(Trigger, 0, AuraType.Dummy)); - AfterEffectProc.Add(new(Trigger, 1, AuraType.Dummy)); - } + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 1, AuraType.PeriodicDamage)); + AfterEffectRemove.Add(new(OnRemove, 1, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); } +} - // 133 - Fireball - [Script] // 11366 - Pyroblast - class spell_mage_firestarter : SpellScript +[Script] // 136511 - Ring of Frost +class spell_mage_ring_of_frost : AuraScript +{ + ObjectGuid _ringOfFrostGuid; + + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Firestarter); - } - - void CalcCritChance(Unit victim, ref float critChance) - { - AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.Firestarter, 0); - if (aurEff != null && victim.GetHealthPct() >= aurEff.GetAmount()) - critChance = 100.0f; - } - - public override void Register() - { - OnCalcCritChance.Add(new(CalcCritChance)); - } - } - - [Script] // 321712 - Pyroblast - class spell_mage_firestarter_dots : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Firestarter); - } - - void CalcCritChance(AuraEffect aurEff, Unit victim, ref float critChance) - { - AuraEffect fireStarterEff = GetCaster().GetAuraEffect(SpellIds.Firestarter, 0); - if (fireStarterEff != null && victim.GetHealthPct() >= aurEff.GetAmount()) - critChance = 100.0f; - } - - public override void Register() - { - DoEffectCalcCritChance.Add(new(CalcCritChance, SpellConst.EffectAll, AuraType.PeriodicDamage)); - } - } - - [Script] // 205029 - Flame On - class spell_mage_flame_on : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FireBlast) - && CliDB.SpellCategoryStorage.HasRecord(SpellMgr.GetSpellInfo(SpellIds.FireBlast, Difficulty.None).ChargeCategoryId) - && ValidateSpellEffect((spellInfo.Id, 2)); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - canBeRecalculated = false; - amount = -(int)MathFunctions.GetPctOf(GetEffectInfo(2).CalcValue() * Time.InMilliseconds, CliDB.SpellCategoryStorage.LookupByKey(SpellMgr.GetSpellInfo(SpellIds.FireBlast, Difficulty.None).ChargeCategoryId).ChargeRecoveryTime); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.ChargeRecoveryMultiplier)); - } - } - - [Script] // 44614 - Flurry - class spell_mage_flurry : SpellScript - { - class FlurryEvent : BasicEvent - { - Unit _caster; - ObjectGuid _target; - ObjectGuid _originalCastId; - int _count; - - public FlurryEvent(Unit caster, ObjectGuid target, ObjectGuid originalCastId, int count) - { - _caster = caster; - _target = target; - _originalCastId = originalCastId; - _count = count; - } - - public override bool Execute(ulong time, uint diff) - { - Unit target = ObjAccessor.GetUnit(_caster, _target); - - if (target == null) - return true; - - _caster.CastSpell(target, SpellIds.FlurryDamage, new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetOriginalCastId(_originalCastId)); - - if (--_count == 0) - return true; - - _caster.m_Events.AddEvent(this, TimeSpan.FromMilliseconds(time) + RandomHelper.RandTime(TimeSpan.FromMilliseconds(300), TimeSpan.FromMilliseconds(400))); - return false; - } - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FlurryDamage); - } - - void EffectHit(uint effIndex) - { - GetCaster().m_Events.AddEventAtOffset(new FlurryEvent(GetCaster(), GetHitUnit().GetGUID(), GetSpell().m_castId, GetEffectValue() - 1), RandomHelper.RandTime(TimeSpan.FromMilliseconds(300), TimeSpan.FromMilliseconds(400))); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(EffectHit, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 228354 - Flurry (damage) - class spell_mage_flurry_damage : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.WintersChill); - } - - void HandleDamage(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.WintersChill, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDamage, 1, SpellEffectName.SchoolDamage)); - } - } - - [Script] // 116 - Frostbolt - class spell_mage_frostbolt : SpellScript - { - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellIds.Chilled); - } - - void HandleChilled() - { - Unit target = GetHitUnit(); - if (target != null) - GetCaster().CastSpell(target, SpellIds.Chilled, TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnHit.Add(new(HandleChilled)); - } - } - - [Script] // 386737 - Hyper Impact - class spell_mage_hyper_impact : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Supernova); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.Supernova, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 11426 - Ice Barrier - class spell_mage_ice_barrier : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Chilled); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - canBeRecalculated = false; - Unit caster = GetCaster(); - if (caster != null) - amount += (int)(caster.SpellBaseHealingBonusDone(GetSpellInfo().GetSchoolMask()) * 10.0f); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = eventInfo.GetDamageInfo().GetVictim(); - Unit target = eventInfo.GetDamageInfo().GetAttacker(); - - if (caster != null && target != null) - caster.CastSpell(target, SpellIds.Chilled, true); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.SchoolAbsorb)); - } - } - - [Script] // 45438 - Ice Block - class spell_mage_ice_block : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EverwarmSocks); - } - - void PreventStunWithEverwarmSocks(ref WorldObject target) - { - if (GetCaster().HasAura(SpellIds.EverwarmSocks)) - target = null; - } - - void PreventEverwarmSocks(ref WorldObject target) - { - if (!GetCaster().HasAura(SpellIds.EverwarmSocks)) - target = null; - } - - public override void Register() - { - OnObjectTargetSelect.Add(new(PreventStunWithEverwarmSocks, 0, Targets.UnitCaster)); - OnObjectTargetSelect.Add(new(PreventEverwarmSocks, 5, Targets.UnitCaster)); - OnObjectTargetSelect.Add(new(PreventEverwarmSocks, 6, Targets.UnitCaster)); - } - } - - [Script] // Ice Lance - 30455 - class spell_mage_ice_lance : SpellScript - { - List _orderedTargets = new(); - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.IceLanceTrigger, SpellIds.ThermalVoid, SpellIds.IcyVeins, SpellIds.ChainReactionDummy, SpellIds.ChainReaction, SpellIds.FingersOfFrost); - } - - void IndexTarget(uint effIndex) - { - _orderedTargets.Add(GetHitUnit().GetGUID()); - } - - void HandleOnHit(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - var index = _orderedTargets.IndexOf(target.GetGUID()); - - if (index == 0 // only primary target triggers these benefits - && target.HasAuraState(AuraStateType.Frozen, GetSpellInfo(), caster)) - { - // Thermal Void - Aura thermalVoid = caster.GetAura(SpellIds.ThermalVoid); - if (thermalVoid != null) - { - if (!thermalVoid.GetSpellInfo().GetEffects().Empty()) - { - Aura icyVeins = caster.GetAura(SpellIds.IcyVeins); - if (icyVeins != null) - icyVeins.SetDuration(icyVeins.GetDuration() + thermalVoid.GetSpellInfo().GetEffect(0).CalcValue(caster) * Time.InMilliseconds); - } - } - - // Chain Reaction - if (caster.HasAura(SpellIds.ChainReactionDummy)) - caster.CastSpell(caster, SpellIds.ChainReaction, true); - } - - // put target index for chain value multiplier into 1 base points, otherwise triggered spell doesn't know which damage multiplier to apply - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint1, index); - caster.CastSpell(target, SpellIds.IceLanceTrigger, args); - } - - public override void Register() - { - OnEffectLaunchTarget.Add(new(IndexTarget, 0, SpellEffectName.ScriptEffect)); - OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 228598 - Ice Lance - class spell_mage_ice_lance_damage : SpellScript - { - void ApplyDamageMultiplier(uint effIndex) - { - SpellValue spellValue = GetSpellValue(); - if ((spellValue.CustomBasePointsMask & (1 << 1)) != 0) - { - int originalDamage = GetHitDamage(); - float targetIndex = (float)(spellValue.EffectBasePoints[1]); - float multiplier = MathF.Pow(GetEffectInfo().CalcDamageMultiplier(GetCaster(), GetSpell()), targetIndex); - SetHitDamage((int)(originalDamage * multiplier)); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(ApplyDamageMultiplier, 0, SpellEffectName.SchoolDamage)); - } - } - - [Script] // 12846 - Ignite - class spell_mage_ignite : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Ignite); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - SpellInfo igniteDot = SpellMgr.GetSpellInfo(SpellIds.Ignite, GetCastDifficulty()); - int pct = aurEff.GetAmount(); - - Cypher.Assert(igniteDot.GetMaxTicks() > 0); - int amount = (int)(MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), pct) / igniteDot.GetMaxTicks()); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.Ignite, args); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - // 37447 - Improved Mana Gems - [Script] // 61062 - Improved Mana Gems - class spell_mage_imp_mana_gems : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ManaSurge); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - eventInfo.GetActor().CastSpell(null, SpellIds.ManaSurge, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - } - - [Script] // 1463 - Incanter's Flow - class spell_mage_incanters_flow : AuraScript - { - int modifier = 1; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.IncantersFlow); - } - - void HandlePeriodicTick(AuraEffect aurEff) - { - // Incanter's flow should not cycle out of combat - if (!GetTarget().IsInCombat()) - return; - - Aura aura = GetTarget().GetAura(SpellIds.IncantersFlow); - if (aura != null) - { - uint stacks = aura.GetStackAmount(); - - // Force always to values between 1 and 5 - if ((modifier == -1 && stacks == 1) || (modifier == 1 && stacks == 5)) - { - modifier *= -1; - return; - } - - aura.ModStackAmount(modifier); - } - else - GetTarget().CastSpell(GetTarget(), SpellIds.IncantersFlow, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodicTick, 0, AuraType.PeriodicDummy)); - } - } - - [Script] // 44457 - Living Bomb - class spell_mage_living_bomb : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LivingBombPeriodic); - } - - void HandleDummy(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - GetCaster().CastSpell(GetHitUnit(), SpellIds.LivingBombPeriodic, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint2, 1)); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 44461 - Living Bomb - class spell_mage_living_bomb_explosion : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return spellInfo.NeedsExplicitUnitTarget() && ValidateSpellInfo(SpellIds.LivingBombPeriodic); - } - - void FilterTargets(List targets) - { - targets.Remove(GetExplTargetWorldObject()); - } - - void HandleSpread(uint effIndex) - { - if (GetSpellValue().EffectBasePoints[0] > 0) - GetCaster().CastSpell(GetHitUnit(), SpellIds.LivingBombPeriodic, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint2, 0)); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(HandleSpread, 1, SpellEffectName.SchoolDamage)); - } - } - - [Script] // 217694 - Living Bomb - class spell_mage_living_bomb_periodic : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LivingBombExplosion); - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; - - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(GetTarget(), SpellIds.LivingBombExplosion, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount())); - } - - public override void Register() - { - AfterEffectRemove.Add(new(AfterRemove, 2, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - /// @todo move out of here and rename - not a mage spell - [Script] // 32826 - Polymorph (Visual) - class spell_mage_polymorph_visual : SpellScript - { - const uint NpcAurosalia = 18744; - - uint[] PolymorhForms = - { - SpellIds.SquirrelForm, - SpellIds.GiraffeForm, - SpellIds.SerpentForm, - SpellIds.DragonhawkForm, - SpellIds.WorgenForm, - SpellIds.SheepForm - }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(PolymorhForms); - } - - void HandleDummy(uint effIndex) - { - Unit target = GetCaster().FindNearestCreature(NpcAurosalia, 30.0f); - if (target != null) - if (target.GetTypeId() == TypeId.Unit) - target.CastSpell(target, PolymorhForms[RandomHelper.IRand(0, 5)], true); - } - - public override void Register() - { - // add dummy effect spell handler to Polymorph visual - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 235450 - Prismatic Barrier - class spell_mage_prismatic_barrier : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 5)); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - canBeRecalculated = false; - Unit caster = GetCaster(); - if (caster != null) - amount = (int)MathFunctions.CalculatePct(caster.GetMaxHealth(), GetEffectInfo(5).CalcValue(caster)); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); - } - } - - [Script] // 376103 - Radiant Spark - class spell_mage_radiant_spark : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RadiantSparkProcBlocker); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Aura vulnerability = procInfo.GetProcTarget().GetAura(aurEff.GetSpellEffectInfo().TriggerSpell, GetCasterGUID()); - if (vulnerability != null && vulnerability.GetStackAmount() == vulnerability.CalcMaxStackAmount()) - { - PreventDefaultAction(); - vulnerability.Remove(); - GetTarget().CastSpell(GetTarget(), SpellIds.RadiantSparkProcBlocker, true); - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 2, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 205021 - Ray of Frost - class spell_mage_ray_of_frost : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RayOfFrostFingersOfFrost); - } - - void HandleOnHit() - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, SpellIds.RayOfFrostFingersOfFrost, TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnHit.Add(new(HandleOnHit)); - } - } - - [Script] - class spell_mage_ray_of_frost_AuraScript : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RayOfFrostBonus, SpellIds.RayOfFrostFingersOfFrost); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster != null) - { - if (aurEff.GetTickNumber() > 1) // First tick should deal base damage - caster.CastSpell(caster, SpellIds.RayOfFrostBonus, true); - } - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - caster.RemoveAurasDueToSpell(SpellIds.RayOfFrostFingersOfFrost); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 1, AuraType.PeriodicDamage)); - AfterEffectRemove.Add(new(OnRemove, 1, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); - } - } - - [Script] // 136511 - Ring of Frost - class spell_mage_ring_of_frost : AuraScript - { - ObjectGuid _ringOfFrostGUID; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RingOfFrostSummon, SpellIds.RingOfFrostFreeze) + return ValidateSpellInfo(SpellIds.RingOfFrostSummon, SpellIds.RingOfFrostFreeze) && ValidateSpellEffect((SpellIds.RingOfFrostSummon, 0)); - } + } - void HandleEffectPeriodic(AuraEffect aurEff) + void HandleEffectPeriodic(AuraEffect aurEff) + { + TempSummon ringOfFrost = GetRingOfFrostMinion(); + if (ringOfFrost != null) + GetTarget().CastSpell(ringOfFrost.GetPosition(), SpellIds.RingOfFrostFreeze, true); + } + + void Apply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + List minions = GetTarget().GetAllMinionsByEntry((uint)Global.SpellMgr.GetSpellInfo(SpellIds.RingOfFrostSummon, GetCastDifficulty()).GetEffect(0).MiscValue); + + // Get the last summoned RoF, save it and despawn older ones + foreach (TempSummon summon in minions) { TempSummon ringOfFrost = GetRingOfFrostMinion(); if (ringOfFrost != null) - GetTarget().CastSpell(ringOfFrost.GetPosition(), SpellIds.RingOfFrostFreeze, true); - } - - void Apply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - List minions = new(); - GetTarget().GetAllMinionsByEntry(minions, (uint)SpellMgr.GetSpellInfo(SpellIds.RingOfFrostSummon, GetCastDifficulty()).GetEffect(0).MiscValue); - - // Get the last summoned RoF, save it and despawn older ones - foreach (TempSummon summon in minions) { - TempSummon ringOfFrost = GetRingOfFrostMinion(); - if (ringOfFrost != null) + if (summon.GetTimer() > ringOfFrost.GetTimer()) { - if (summon.GetTimer() > ringOfFrost.GetTimer()) - { - ringOfFrost.DespawnOrUnsummon(); - _ringOfFrostGUID = summon.GetGUID(); - } - else - summon.DespawnOrUnsummon(); + ringOfFrost.DespawnOrUnsummon(); + _ringOfFrostGuid = summon.GetGUID(); } else - _ringOfFrostGUID = summon.GetGUID(); + summon.DespawnOrUnsummon(); } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); - OnEffectApply.Add(new(Apply, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.RealOrReapplyMask)); - } - - TempSummon GetRingOfFrostMinion() - { - Creature creature = ObjectAccessor.GetCreature(GetOwner(), _ringOfFrostGUID); - if (creature != null) - return creature.ToTempSummon(); - return null; + else + _ringOfFrostGuid = summon.GetGUID(); } } - [Script] // 82691 - Ring of Frost (freeze efect) - class spell_mage_ring_of_frost_freeze : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RingOfFrostSummon, SpellIds.RingOfFrostFreeze) + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); + OnEffectApply.Add(new(Apply, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.RealOrReapplyMask)); + } + + TempSummon GetRingOfFrostMinion() + { + Creature creature = ObjectAccessor.GetCreature(GetOwner(), _ringOfFrostGuid); + if (creature != null) + return creature.ToTempSummon(); + return null; + } +} + +[Script] // 82691 - Ring of Frost (freeze efect) +class spell_mage_ring_of_frost_freeze : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RingOfFrostSummon, SpellIds.RingOfFrostFreeze) && ValidateSpellEffect((SpellIds.RingOfFrostSummon, 0)); - } + } - void FilterTargets(List targets) + void FilterTargets(List targets) + { + WorldLocation dest = GetExplTargetDest(); + float outRadius = Global.SpellMgr.GetSpellInfo(SpellIds.RingOfFrostSummon, GetCastDifficulty()).GetEffect(0).CalcRadius(null, SpellTargetIndex.TargetB); + float inRadius = 6.5f; + + targets.RemoveAll(target => { - WorldLocation dest = GetExplTargetDest(); - float outRadius = SpellMgr.GetSpellInfo(SpellIds.RingOfFrostSummon, GetCastDifficulty()).GetEffect(0).CalcRadius(null, SpellTargetIndex.TargetB); - float inRadius = 6.5f; + Unit unit = target.ToUnit(); + if (unit == null) + return true; + return unit.HasAura(SpellIds.RingOfFrostDummy) || unit.HasAura(SpellIds.RingOfFrostFreeze) || unit.GetExactDist(dest) > outRadius || unit.GetExactDist(dest) < inRadius; + }); + } - targets.RemoveAll(target => + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); + } +} + +[Script] +class spell_mage_ring_of_frost_freeze_AuraScript : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RingOfFrostDummy); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + if (GetCaster() != null) + GetCaster().CastSpell(GetTarget(), SpellIds.RingOfFrostDummy, true); + } + + public override void Register() + { + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); + } +} + +[Script] // 450746 - Scald (attached to 2948 - Scorch) +class spell_mage_scald : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Scald) + && ValidateSpellEffect((spellInfo.Id, 1)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.Scald); + } + + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + if (!victim.HealthBelowPct(GetEffectInfo(1).CalcValue(GetCaster()))) + return; + + AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.Scald, 0); + if (aurEff != null) + MathFunctions.AddPct(ref pctMod, aurEff.GetAmount()); + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamage)); + } +} + +[Script] // 2948 - Scorch +class spell_mage_scorch : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FreneticSpeed); + } + + void CalcCritChance(Unit victim, ref float critChance) + { + if (victim.GetHealthPct() < GetEffectInfo(1).CalcValue(GetCaster())) + critChance = 100.0f; + } + + void HandleFreneticSpeed(uint effIndex) + { + Unit caster = GetCaster(); + if (GetHitUnit().GetHealthPct() < GetEffectInfo(1).CalcValue(GetCaster())) + caster.CastSpell(caster, SpellIds.FreneticSpeed, new CastSpellExtraArgs() { - Unit unit = target.ToUnit(); - if (unit == null) - return true; - return unit.HasAura(SpellIds.RingOfFrostDummy) || unit.HasAura(SpellIds.RingOfFrostFreeze) || unit.GetExactDist(dest) > outRadius || unit.GetExactDist(dest) < inRadius; + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() }); - } + } - public override void Register() + public override void Register() + { + OnCalcCritChance.Add(new(CalcCritChance)); + OnEffectHitTarget.Add(new(HandleFreneticSpeed, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 451875 - Spontaneous Combustion (attached to 190319 - Combustion) +class spell_mage_spontaneous_combustion : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SpontaneousCombustion, SpellIds.FireBlast, SpellIds.PhoenixFlames); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.SpontaneousCombustion); + } + + void HandleCharges() + { + GetCaster().GetSpellHistory().ResetCharges(Global.SpellMgr.GetSpellInfo(SpellIds.FireBlast, Difficulty.None).ChargeCategoryId); + GetCaster().GetSpellHistory().ResetCharges(Global.SpellMgr.GetSpellInfo(SpellIds.PhoenixFlames, Difficulty.None).ChargeCategoryId); + } + + public override void Register() + { + AfterCast.Add(new(HandleCharges)); + } +} + +[Script] // 157980 - Supernova +class spell_mage_supernova : SpellScript +{ + void HandleDamage(uint effIndex) + { + if (GetExplTargetUnit() == GetHitUnit()) { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); + int damage = GetHitDamage(); + MathFunctions.AddPct(ref damage, GetEffectInfo(0).CalcValue()); + SetHitDamage(damage); } } - [Script] - class spell_mage_ring_of_frost_freeze_AuraScript : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RingOfFrostDummy); - } + OnEffectHitTarget.Add(new(HandleDamage, 1, SpellEffectName.SchoolDamage)); + } +} - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - if (GetCaster() != null) - GetCaster().CastSpell(GetTarget(), SpellIds.RingOfFrostDummy, true); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); - } +[Script] // 382289 - Tempest Barrier +class spell_mage_tempest_barrier : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TempestBarrierAbsorb); } - [Script] // 157980 - Supernova - class spell_mage_supernova : SpellScript + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - void HandleDamage(uint effIndex) + PreventDefaultAction(); + Unit target = GetTarget(); + int amount = (int)MathFunctions.CalculatePct(target.GetMaxHealth(), aurEff.GetAmount()); + target.CastSpell(target, SpellIds.TempestBarrierAbsorb, new CastSpellExtraArgs() { - if (GetExplTargetUnit() == GetHitUnit()) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, amount) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 210824 - Touch of the Magi (Aura) +class spell_mage_touch_of_the_magi_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TouchOfTheMagiExplode); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo != null) + { + if (damageInfo.GetAttacker() == GetCaster() && damageInfo.GetVictim() == GetTarget()) { - int damage = GetHitDamage(); - MathFunctions.AddPct(ref damage, GetEffectInfo(0).CalcValue()); - SetHitDamage(damage); + uint extra = MathFunctions.CalculatePct(damageInfo.GetDamage(), 25); + if (extra > 0) + aurEff.ChangeAmount((int)(aurEff.GetAmount() + extra)); } } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDamage, 1, SpellEffectName.SchoolDamage)); - } } - [Script] // 210824 - Touch of the Magi (Aura) - class spell_mage_touch_of_the_magi : AuraScript + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.TouchOfTheMagiExplode); - } + int amount = aurEff.GetAmount(); + if (amount == 0 || GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo != null) - { - if (damageInfo.GetAttacker() == GetCaster() && damageInfo.GetVictim() == GetTarget()) - { - uint extra = MathFunctions.CalculatePct(damageInfo.GetDamage(), 25); - if (extra > 0) - aurEff.ChangeAmount(aurEff.GetAmount() + (int)extra); - } - } - } - - void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - int amount = aurEff.GetAmount(); - if (amount == 0 || GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; - - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(GetTarget(), SpellIds.TouchOfTheMagiExplode, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, amount)); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.TouchOfTheMagiExplode, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, amount)); } - [Script] // 33395 Water Elemental's Freeze - class spell_mage_water_elemental_freeze : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FingersOfFrost); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - void HandleImprovedFreeze() - { - Unit owner = GetCaster().GetOwner(); - if (owner == null) - return; +[Script] // 33395 Water Elemental's Freeze +class spell_mage_water_elemental_freeze : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FingersOfFrost); + } - owner.CastSpell(owner, SpellIds.FingersOfFrost, true); - } + void HandleImprovedFreeze() + { + Unit owner = GetCaster().GetOwner(); + if (owner == null) + return; - public override void Register() - { - AfterHit.Add(new(HandleImprovedFreeze)); - } + owner.CastSpell(owner, SpellIds.FingersOfFrost, true); + } + + public override void Register() + { + AfterHit.Add(new(HandleImprovedFreeze)); } } \ No newline at end of file diff --git a/Source/Scripts/Spells/Monk.cs b/Source/Scripts/Spells/Monk.cs index 6b7e227f3..4874fa821 100644 --- a/Source/Scripts/Spells/Monk.cs +++ b/Source/Scripts/Spells/Monk.cs @@ -1,519 +1,768 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; +using Game.AI; using Game.Entities; +using Game.Movement; using Game.Scripting; using Game.Spells; -using static Global; +using System.Collections.Generic; -namespace Scripts.Spells.Monk +namespace Scripts.Spells.Monk; + +struct SpellIds { - struct SpellIds + public const uint BurstOfLifeTalent = 399226; + public const uint BurstOfLifeHeal = 399230; + public const uint CalmingCoalescence = 388220; + public const uint CombatConditioning = 128595; + public const uint CracklingJadeLightningChannel = 117952; + public const uint CracklingJadeLightningChiProc = 123333; + public const uint CracklingJadeLightningKnockback = 117962; + public const uint CracklingJadeLightningKnockbackCd = 117953; + public const uint EnvelopingMist = 124682; + public const uint JadeWalk = 450552; + public const uint MistsOfLife = 388548; + public const uint MortalWounds = 115804; + public const uint PowerStrikeProc = 129914; + public const uint PowerStrikeEnergize = 121283; + public const uint PressurePoints = 450432; + public const uint ProvokeSingleTarget = 116189; + public const uint ProvokeAoe = 118635; + public const uint NoFeatherFall = 79636; + public const uint OpenPalmStrikesTalent = 392970; + public const uint RenewingMist = 119611; + public const uint RollBackward = 109131; + public const uint RollForward = 107427; + public const uint SaveThemAllHealBonus = 390105; + public const uint SongOfChiJiStun = 198909; + public const uint SoothingMist = 115175; + public const uint StanceOfTheSpiritedCrane = 154436; + public const uint StaggerDamageAura = 124255; + public const uint StaggerHeavy = 124273; + public const uint StaggerLight = 124275; + public const uint StaggerModerate = 124274; + public const uint SurgingMistHeal = 116995; + + // Utility for stagger scripts + public static Aura FindExistingStaggerEffect(Unit unit) { - public const uint CalmingCoalescence = 388220; - public const uint CracklingJadeLightningChannel = 117952; - public const uint CracklingJadeLightningChiProc = 123333; - public const uint CracklingJadeLightningKnockback = 117962; - public const uint CracklingJadeLightningKnockbackCd = 117953; - public const uint PowerStrikeProc = 129914; - public const uint PowerStrikeEnergize = 121283; - public const uint ProvokeSingleTarget = 116189; - public const uint ProvokeAoe = 118635; - public const uint NoFeatherFall = 79636; - public const uint OpenPalmStrikesTalent = 392970; - public const uint RollBackward = 109131; - public const uint RollForward = 107427; - public const uint SoothingMist = 115175; - public const uint StanceOfTheSpiritedCrane = 154436; - public const uint StaggerDamageAura = 124255; - public const uint StaggerHeavy = 124273; - public const uint StaggerLight = 124275; - public const uint StaggerModerate = 124274; - public const uint SurgingMistHeal = 116995; + Aura auraLight = unit.GetAura(StaggerLight); + if (auraLight != null) + return auraLight; + Aura auraModerate = unit.GetAura(StaggerModerate); + if (auraModerate != null) + return auraModerate; + Aura auraHeavy = unit.GetAura(StaggerHeavy); + if (auraHeavy != null) + return auraHeavy; + + return null; + } +} + +[Script] // 399226 - Burst of Life (attached to 116849 - Life Cocoon) +class spell_monk_burst_of_life : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BurstOfLifeHeal) + && ValidateSpellEffect((SpellIds.BurstOfLifeTalent, 0)); } - struct MonkUtility + public override bool Load() { - // Utility for stagger scripts - public static Aura FindExistingStaggerEffect(Unit unit) - { - Aura auraLight = unit.GetAura(SpellIds.StaggerLight); - if (auraLight != null) - return auraLight; - - Aura auraModerate = unit.GetAura(SpellIds.StaggerModerate); - if (auraModerate != null) - return auraModerate; - - Aura auraHeavy = unit.GetAura(SpellIds.StaggerHeavy); - if (auraHeavy != null) - return auraHeavy; - - return null; - } + Unit caster = GetCaster(); + return caster != null && caster.HasAuraEffect(SpellIds.BurstOfLifeTalent, 0); } - [Script] // 117952 - Crackling Jade Lightning - class spell_monk_crackling_jade_lightning : AuraScript + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.StanceOfTheSpiritedCrane, SpellIds.CracklingJadeLightningChiProc); - } + AuraRemoveMode removeMode = GetTargetApplication().GetRemoveMode(); + if (removeMode != AuraRemoveMode.Expire && (removeMode != AuraRemoveMode.EnemySpell || aurEff.GetAmount() != 0)) + return; - void OnTick(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster != null) - if (caster.HasAura(SpellIds.StanceOfTheSpiritedCrane)) - caster.CastSpell(caster, SpellIds.CracklingJadeLightningChiProc, TriggerCastFlags.FullMask); - } + Unit caster = GetCaster(); + if (caster == null) + return; - public override void Register() + AuraEffect burstOfLife = caster.GetAuraEffect(SpellIds.BurstOfLifeTalent, 0); + if (burstOfLife == null) + return; + + caster.CastSpell(GetTarget(), SpellIds.BurstOfLifeHeal, new CastSpellExtraArgs() { - OnEffectPeriodic.Add(new(OnTick, 0, AuraType.PeriodicDamage)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = [new(SpellValueMod.MaxTargets, burstOfLife.GetAmount())] + }); } - [Script] // 117959 - Crackling Jade Lightning - class spell_monk_crackling_jade_lightning_knockback_proc : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CracklingJadeLightningKnockback, - SpellIds.CracklingJadeLightningKnockbackCd - ); - } + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.Real)); + } +} - bool CheckProc(ProcEventInfo eventInfo) - { - if (GetTarget().HasAura(SpellIds.CracklingJadeLightningKnockbackCd)) - return false; - - if (eventInfo.GetActor().HasAura(SpellIds.CracklingJadeLightningChannel, GetTarget().GetGUID())) - return false; - - Spell currentChanneledSpell = GetTarget().GetCurrentSpell(CurrentSpellTypes.Channeled); - if (currentChanneledSpell == null || currentChanneledSpell.GetSpellInfo().Id != SpellIds.CracklingJadeLightningChannel) - return false; - - return true; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().CastSpell(eventInfo.GetActor(), SpellIds.CracklingJadeLightningKnockback, TriggerCastFlags.FullMask); - GetTarget().CastSpell(GetTarget(), SpellIds.CracklingJadeLightningKnockbackCd, TriggerCastFlags.FullMask); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 399230 - Burst of Life +class spell_monk_burst_of_life_heal : SpellScript +{ + void FilterTargets(List targets) + { + SelectRandomInjuredTargets(targets, GetSpellValue().MaxAffectedTargets, true, GetExplTargetUnit()); } - [Script] // 116849 - Life Cocoon - class spell_monk_life_cocoon : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CalmingCoalescence); - } + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaAlly)); + } +} - void CalculateAbsorb(uint effIndex) - { - int absorb = (int)GetCaster().CountPctFromMaxHealth(GetEffectValue()); - Player player = GetCaster().ToPlayer(); - if (player != null) - MathFunctions.AddPct(ref absorb, player.GetRatingBonusValue(CombatRating.VersatilityHealingDone)); +[Script] // 117952 - Crackling Jade Lightning +class spell_monk_crackling_jade_lightning : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StanceOfTheSpiritedCrane, SpellIds.CracklingJadeLightningChiProc); + } - AuraEffect calmingCoalescence = GetCaster().GetAuraEffect(SpellIds.CalmingCoalescence, 0, GetCaster().GetGUID()); - if (calmingCoalescence != null) + void OnTick(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + if (caster.HasAura(SpellIds.StanceOfTheSpiritedCrane)) + caster.CastSpell(caster, SpellIds.CracklingJadeLightningChiProc, TriggerCastFlags.FullMask); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(OnTick, 0, AuraType.PeriodicDamage)); + } +} + +[Script] // 117959 - Crackling Jade Lightning +class spell_monk_crackling_jade_lightning_knockback_proc_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CracklingJadeLightningKnockback, SpellIds.CracklingJadeLightningKnockbackCd); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (GetTarget().HasAura(SpellIds.CracklingJadeLightningKnockbackCd)) + return false; + + if (eventInfo.GetActor().HasAura(SpellIds.CracklingJadeLightningChannel, GetTarget().GetGUID())) + return false; + + Spell currentChanneledSpell = GetTarget().GetCurrentSpell(CurrentSpellTypes.Channeled); + if (currentChanneledSpell == null || currentChanneledSpell.GetSpellInfo().Id != SpellIds.CracklingJadeLightningChannel) + return false; + + return true; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(eventInfo.GetActor(), SpellIds.CracklingJadeLightningKnockback, TriggerCastFlags.FullMask); + GetTarget().CastSpell(GetTarget(), SpellIds.CracklingJadeLightningKnockbackCd, TriggerCastFlags.FullMask); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 450553 - Jade Walk +class spell_monk_jade_walk : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.JadeWalk); + } + + void HandlePeriodicTick(AuraEffect aurEff) + { + Unit target = GetTarget(); + if (!target.IsInCombat()) + { + target.CastSpell(target, SpellIds.JadeWalk, new CastSpellExtraArgs() { - MathFunctions.AddPct(ref absorb, calmingCoalescence.GetAmount()); - calmingCoalescence.GetBase().Remove(); - } - - GetSpell().SetSpellValue(new((int)SpellValueMod.BasePoint0, absorb)); - } - - public override void Register() - { - OnEffectLaunch.Add(new(CalculateAbsorb, 2, SpellEffectName.Dummy)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff, + }); } + else + target.RemoveAurasDueToSpell(SpellIds.JadeWalk); } - [Script] // 392972 - Open Palm Strikes - class spell_monk_open_palm_strikes : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.OpenPalmStrikesTalent, 1)); - } + OnEffectPeriodic.Add(new(HandlePeriodicTick, 0, AuraType.PeriodicTriggerSpell)); + } +} - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - AuraEffect talent = GetTarget().GetAuraEffect(SpellIds.OpenPalmStrikesTalent, 1); - return talent != null && RandomHelper.randChance(talent.GetAmount()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } +[Script] // 116849 - Life Cocoon +class spell_monk_life_cocoon : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CalmingCoalescence); } - [Script] // 121817 - Power Strike - class spell_monk_power_strike_periodic : AuraScript + void CalculateAbsorb(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) + int absorb = (int)GetCaster().CountPctFromMaxHealth(GetEffectValue()); + Player player = GetCaster().ToPlayer(); + if (player != null) + MathFunctions.AddPct(ref absorb, player.GetRatingBonusValue(CombatRating.VersatilityHealingDone)); + + AuraEffect calmingCoalescence = GetCaster().GetAuraEffect(SpellIds.CalmingCoalescence, 0, GetCaster().GetGUID()); + if (calmingCoalescence != null) { - return ValidateSpellInfo(SpellIds.PowerStrikeProc); + MathFunctions.AddPct(ref absorb, calmingCoalescence.GetAmount()); + calmingCoalescence.GetBase().Remove(); } - void HandlePeriodic(AuraEffect aurEff) - { - GetTarget().CastSpell(GetTarget(), SpellIds.PowerStrikeProc, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDummy)); - } + GetSpell().SetSpellValue(new(SpellValueMod.BasePoint0, absorb)); } - [Script] // 129914 - Power Strike Proc - class spell_monk_power_strike_proc : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerStrikeEnergize); - } + OnEffectLaunch.Add(new(CalculateAbsorb, 2, SpellEffectName.Dummy)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().CastSpell(GetTarget(), SpellIds.PowerStrikeEnergize, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 388548 - Mists of Life (attached to 116849 - Life Cocoon) +class spell_monk_mists_of_life : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MistsOfLife, SpellIds.RenewingMist, SpellIds.EnvelopingMist); } - [Script] // 115546 - Provoke - class spell_monk_provoke : SpellScript + public override bool Load() { - const uint BlackOxStatusEntry = 61146; - - public override bool Validate(SpellInfo spellInfo) - { - if (!spellInfo.GetExplicitTargetMask().HasFlag(SpellCastTargetFlags.UnitMask)) // ensure GetExplTargetUnit() will return something meaningful during CheckCast - return false; - return ValidateSpellInfo(SpellIds.ProvokeSingleTarget, - SpellIds.ProvokeAoe - ); - } - - SpellCastResult CheckExplicitTarget() - { - if (GetExplTargetUnit().GetEntry() != BlackOxStatusEntry) - { - SpellInfo singleTarget = SpellMgr.GetSpellInfo(SpellIds.ProvokeSingleTarget, GetCastDifficulty()); - SpellCastResult singleTargetExplicitResult = singleTarget.CheckExplicitTarget(GetCaster(), GetExplTargetUnit()); - if (singleTargetExplicitResult != SpellCastResult.SpellCastOk) - return singleTargetExplicitResult; - } - else if (GetExplTargetUnit().GetOwnerGUID() != GetCaster().GetGUID()) - return SpellCastResult.BadTargets; - - return SpellCastResult.SpellCastOk; - } - - void HandleDummy(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - if (GetHitUnit().GetEntry() != BlackOxStatusEntry) - GetCaster().CastSpell(GetHitUnit(), SpellIds.ProvokeSingleTarget, true); - else - GetCaster().CastSpell(GetHitUnit(), SpellIds.ProvokeAoe, true); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckExplicitTarget)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + return GetCaster().HasAuraEffect(SpellIds.MistsOfLife, 0); } - [Script] // 109132 - Roll - class spell_monk_roll : SpellScript + void HandleEffectApply(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RollBackward, SpellIds.RollForward, SpellIds.NoFeatherFall); - } + Unit caster = GetCaster(); + Unit target = GetHitUnit(); - SpellCastResult CheckCast() - { - if (GetCaster().HasUnitState(UnitState.Root)) - return SpellCastResult.Rooted; - return SpellCastResult.SpellCastOk; - } + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.IgnoreCastTime | TriggerCastFlags.DontReportCastError); + args.SetTriggeringSpell(GetSpell()); - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), GetCaster().HasUnitMovementFlag(MovementFlag.Backward) ? SpellIds.RollBackward : SpellIds.RollForward, - TriggerCastFlags.IgnoreCastInProgress); - GetCaster().CastSpell(GetCaster(), SpellIds.NoFeatherFall, true); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + caster.CastSpell(target, SpellIds.RenewingMist, args); + caster.CastSpell(target, SpellIds.EnvelopingMist, args); } - // 107427 - Roll - [Script] // 109131 - Roll (backward) - class spell_monk_roll_AuraScript : AuraScript + public override void Register() { - void CalcMovementAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - amount += 100; - } + OnEffectHitTarget.Add(new(HandleEffectApply, 0, SpellEffectName.ApplyAura)); + } +} - void CalcImmunityAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - amount -= 100; - } - - void ChangeRunBackSpeed(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().SetSpeed(UnitMoveType.RunBack, GetTarget().GetSpeed(UnitMoveType.Run)); - } - - void RestoreRunBackSpeed(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().UpdateSpeed(UnitMoveType.RunBack); - } - - public override void Register() - { - // Values need manual correction - DoEffectCalcAmount.Add(new(CalcMovementAmount, 0, AuraType.ModSpeedNoControl)); - DoEffectCalcAmount.Add(new(CalcMovementAmount, 2, AuraType.ModMinimumSpeed)); - DoEffectCalcAmount.Add(new(CalcImmunityAmount, 5, AuraType.MechanicImmunity)); - DoEffectCalcAmount.Add(new(CalcImmunityAmount, 6, AuraType.MechanicImmunity)); - - // This is a special aura that sets backward run speed equal to forward speed - AfterEffectApply.Add(new(ChangeRunBackSpeed, 4, AuraType.UseNormalMovementSpeed, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(RestoreRunBackSpeed, 4, AuraType.UseNormalMovementSpeed, AuraEffectHandleModes.Real)); - } +[Script] // 392972 - Open Palm Strikes +class spell_monk_open_palm_strikes : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.OpenPalmStrikesTalent, 1)); } - [Script] // 115069 - Stagger - class spell_monk_stagger : AuraScript + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.StaggerLight, SpellIds.StaggerModerate, SpellIds.StaggerHeavy); - } + AuraEffect talent = GetTarget().GetAuraEffect(SpellIds.OpenPalmStrikesTalent, 1); + return talent != null && RandomHelper.randChance(talent.GetAmount()); + } - void AbsorbNormal(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - Absorb(dmgInfo, 1.0f); - } + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} - void AbsorbMagic(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) +[Script] // 121817 - Power Strike +class spell_monk_power_strike_periodic : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerStrikeProc); + } + + void HandlePeriodic(AuraEffect aurEff) + { + GetTarget().CastSpell(GetTarget(), SpellIds.PowerStrikeProc, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 129914 - Power Strike Proc +class spell_monk_power_strike_proc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerStrikeEnergize); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(GetTarget(), SpellIds.PowerStrikeEnergize, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 115078 - Paralysis +class spell_monk_pressure_points : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PressurePoints) + && ValidateSpellEffect((spellInfo.Id, 2)) + && spellInfo.GetEffect(2).IsEffect(SpellEffectName.Dispel); + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.PressurePoints); + } + + static void PreventDispel(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(PreventDispel, 2, Targets.UnitTargetEnemy)); + } +} + +[Script] // 115546 - Provoke +class spell_monk_provoke : SpellScript +{ + const uint BlackOxStatusEntry = 61146; + + public override bool Validate(SpellInfo spellInfo) + { + if ((spellInfo.GetExplicitTargetMask() & SpellCastTargetFlags.UnitMask) == 0) // ensure GetExplTargetUnit() will return something meaningful during CheckCast + return false; + return ValidateSpellInfo(SpellIds.ProvokeSingleTarget, SpellIds.ProvokeAoe); + } + + SpellCastResult CheckExplicitTarget() + { + if (GetExplTargetUnit().GetEntry() != BlackOxStatusEntry) { - AuraEffect effect = GetEffect(4); - if (effect == null) + SpellInfo singleTarget = Global.SpellMgr.GetSpellInfo(SpellIds.ProvokeSingleTarget, GetCastDifficulty()); + SpellCastResult singleTargetExplicitResult = singleTarget.CheckExplicitTarget(GetCaster(), GetExplTargetUnit()); + if (singleTargetExplicitResult != SpellCastResult.SpellCastOk) + return singleTargetExplicitResult; + } + else if (GetExplTargetUnit().GetOwnerGUID() != GetCaster().GetGUID()) + return SpellCastResult.BadTargets; + + return SpellCastResult.SpellCastOk; + } + + void HandleDummy(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + if (GetHitUnit().GetEntry() != BlackOxStatusEntry) + GetCaster().CastSpell(GetHitUnit(), SpellIds.ProvokeSingleTarget, true); + else + GetCaster().CastSpell(GetHitUnit(), SpellIds.ProvokeAoe, true); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckExplicitTarget)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 107428 - Rising Sun Kick +class spell_monk_rising_sun_kick : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CombatConditioning, SpellIds.MortalWounds); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.CombatConditioning); + } + + void HandleOnHit(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.MortalWounds, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectLaunchTarget.Add(new(HandleOnHit, 0, SpellEffectName.TriggerSpell)); + } +} + +[Script] // 109132 - Roll +class spell_monk_roll : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RollBackward, SpellIds.RollForward, SpellIds.NoFeatherFall); + } + + SpellCastResult CheckCast() + { + if (GetCaster().HasUnitState(UnitState.Root)) + return SpellCastResult.Rooted; + return SpellCastResult.SpellCastOk; + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), GetCaster().HasUnitMovementFlag(MovementFlag.Backward) ? SpellIds.RollBackward : SpellIds.RollForward, TriggerCastFlags.IgnoreCastInProgress); + GetCaster().CastSpell(GetCaster(), SpellIds.NoFeatherFall, true); + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// 107427 - Roll +[Script] // 109131 - Roll (backward) +class spell_monk_roll_aura : AuraScript +{ + void CalcMovementAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + amount += 100; + } + + void CalcImmunityAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + amount -= 100; + } + + void ChangeRunBackSpeed(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().SetSpeed(UnitMoveType.RunBack, GetTarget().GetSpeed(UnitMoveType.Run)); + } + + void RestoreRunBackSpeed(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().UpdateSpeed(UnitMoveType.RunBack); + } + + public override void Register() + { + // Values need manual correction + DoEffectCalcAmount.Add(new(CalcMovementAmount, 0, AuraType.ModSpeedNoControl)); + DoEffectCalcAmount.Add(new(CalcMovementAmount, 2, AuraType.ModMinimumSpeed)); + DoEffectCalcAmount.Add(new(CalcImmunityAmount, 5, AuraType.MechanicImmunity)); + DoEffectCalcAmount.Add(new(CalcImmunityAmount, 6, AuraType.MechanicImmunity)); + + // This is a special aura that sets backward run speed equal to forward speed + AfterEffectApply.Add(new(ChangeRunBackSpeed, 4, AuraType.UseNormalMovementSpeed, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(RestoreRunBackSpeed, 4, AuraType.UseNormalMovementSpeed, AuraEffectHandleModes.Real)); + } +} + +[Script] // 389579 - Save Them All +class spell_monk_save_them_all : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SaveThemAllHealBonus) + && ValidateSpellEffect((spellInfo.Id, 2)); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetActionTarget().HealthBelowPct(GetEffectInfo(2).CalcValue(eventInfo.GetActor())); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(GetTarget(), SpellIds.SaveThemAllHealBonus, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 198898 - Song of Chi-Ji +class at_monk_song_of_chi_ji(AreaTrigger areatrigger) : AreaTriggerAI(areatrigger) +{ + public override void OnInitialize() + { + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(at.GetSpellId(), Difficulty.None); + if (spellInfo == null) + return; + + Unit caster = at.GetCaster(); + if (caster == null) + return; + + Position destPos = at.GetFirstCollisionPosition(spellInfo.GetMaxRange(false, caster), 0.0f); + PathGenerator path = new(at); + + path.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false); + + at.InitSplines(path.GetPath()); + } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, SpellIds.SongOfChiJiStun, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } +} + +[Script] // 115069 - Stagger +class spell_monk_stagger : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StaggerLight, SpellIds.StaggerModerate, SpellIds.StaggerHeavy); + } + + void AbsorbNormal(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + Absorb(dmgInfo, 1.0f); + } + + void AbsorbMagic(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + AuraEffect effect = GetEffect(4); + if (effect == null) + return; + + Absorb(dmgInfo, (float)effect.GetAmount() / 100.0f); + } + + void Absorb(DamageInfo dmgInfo, float multiplier) + { + // Prevent default action (which would remove the aura) + PreventDefaultAction(); + + // make sure damage doesn't come from stagger damage spell StaggerDamageAura + SpellInfo dmgSpellInfo = dmgInfo.GetSpellInfo(); + if (dmgSpellInfo != null) + if (dmgSpellInfo.Id == SpellIds.StaggerDamageAura) return; - Absorb(dmgInfo, (float)(effect.GetAmount()) / 100.0f); - } + AuraEffect effect = GetEffect(0); + if (effect == null) + return; - void Absorb(DamageInfo dmgInfo, float multiplier) + Unit target = GetTarget(); + float agility = target.GetStat(Stats.Agility); + float base1 = MathFunctions.CalculatePct(agility, (float)effect.GetAmount()); + float K = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, target.GetLevel(), -2, 0, target.GetClass(), 0); + + float newAmount = (base1 / (base1 + K)); + newAmount *= multiplier; + + // Absorb X percentage of the damage + float absorbAmount = (float)dmgInfo.GetDamage() * newAmount; + if (absorbAmount > 0) { - // Prevent default action (which would Remove the aura) - PreventDefaultAction(); + uint tempAbsorb = (uint)absorbAmount; + dmgInfo.AbsorbDamage(ref tempAbsorb); + absorbAmount = tempAbsorb; - // make sure damage doesn't come from stagger damage spell SpellIds.StaggerDamageAura - SpellInfo dmgSpellInfo = dmgInfo.GetSpellInfo(); - if (dmgSpellInfo != null && dmgSpellInfo.Id == SpellIds.StaggerDamageAura) + // Cast stagger and make it tick on each tick + AddAndRefreshStagger(absorbAmount); + } + } + + public override void Register() + { + OnEffectAbsorb.Add(new(AbsorbNormal, 1)); + OnEffectAbsorb.Add(new(AbsorbMagic, 2)); + } + + void AddAndRefreshStagger(float amount) + { + Unit target = GetTarget(); + Aura auraStagger = SpellIds.FindExistingStaggerEffect(target); + if (auraStagger != null) + { + AuraEffect effStaggerRemaining = auraStagger.GetEffect(1); + if (effStaggerRemaining == null) return; - AuraEffect effect = GetEffect(0); - if (effect == null) - return; - - Unit target = GetTarget(); - float agility = target.GetStat(Stats.Agility); - float baseAmount = MathFunctions.CalculatePct(agility, (float)(effect.GetAmount())); - float K = DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, target.GetLevel(), -2, 0, target.GetClass(), 0); - - float newAmount = (baseAmount / (baseAmount + K)); - newAmount *= multiplier; - - // Absorb X percentage of the damage - float absorbAmount = (float)(dmgInfo.GetDamage()) * newAmount; - if (absorbAmount > 0) + float newAmount = effStaggerRemaining.GetAmount() + amount; + uint spellId = GetStaggerSpellId(target, newAmount); + if (spellId == effStaggerRemaining.GetSpellInfo().Id) { - dmgInfo.AbsorbDamage((uint)absorbAmount); - - // Cast stagger and make it tick on each tick - AddAndRefreshStagger(absorbAmount); - } - } - - public override void Register() - { - OnEffectAbsorb.Add(new(AbsorbNormal, 1)); - OnEffectAbsorb.Add(new(AbsorbMagic, 2)); - } - - void AddAndRefreshStagger(float amount) - { - Unit target = GetTarget(); - Aura auraStagger = MonkUtility.FindExistingStaggerEffect(target); - if (auraStagger != null) - { - AuraEffect effStaggerRemaining = auraStagger.GetEffect(1); - if (effStaggerRemaining == null) - return; - - float newAmount = effStaggerRemaining.GetAmount() + amount; - uint spellId = GetStaggerSpellId(target, newAmount); - if (spellId == effStaggerRemaining.GetSpellInfo().Id) - { - auraStagger.RefreshDuration(); - effStaggerRemaining.ChangeAmount((int)newAmount, false, true); - } - else - { - // amount changed the stagger type so we need to change the stagger amount (e.g. from medium to light) - GetTarget().RemoveAura(auraStagger); - AddNewStagger(target, spellId, newAmount); - } + auraStagger.RefreshDuration(); + effStaggerRemaining.ChangeAmount((int)newAmount, false, true); } else - AddNewStagger(target, GetStaggerSpellId(target, amount), amount); + { + // amount changed the stagger type so we need to change the stagger amount (e.g. from medium to light) + GetTarget().RemoveAura(auraStagger); + AddNewStagger(target, spellId, newAmount); + } } + else + AddNewStagger(target, GetStaggerSpellId(target, amount), amount); + } - uint GetStaggerSpellId(Unit unit, float amount) + uint GetStaggerSpellId(Unit unit, float amount) + { + const float StaggerHeavy = 0.6f; + const float StaggerModerate = 0.3f; + + float staggerPct = amount / (float)unit.GetMaxHealth(); + return (staggerPct >= StaggerHeavy) ? SpellIds.StaggerHeavy : + (staggerPct >= StaggerModerate) ? SpellIds.StaggerModerate : SpellIds.StaggerLight; + } + + void AddNewStagger(Unit unit, uint staggerSpellId, float staggerAmount) + { + // We only set the total stagger amount. The amount per tick will be set by the stagger spell script + unit.CastSpell(unit, staggerSpellId, new CastSpellExtraArgs(SpellValueMod.BasePoint1, (int)staggerAmount).SetTriggerFlags(TriggerCastFlags.FullMask)); + } +} + +[Script] // 124255 - Stagger - StaggerDamageAura +class spell_monk_stagger_damage_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StaggerLight, SpellIds.StaggerModerate, SpellIds.StaggerHeavy); + } + + void OnPeriodicDamage(AuraEffect aurEff) + { + // Update our light/medium/heavy stagger with the correct stagger amount left + Aura auraStagger = SpellIds.FindExistingStaggerEffect(GetTarget()); + if (auraStagger != null) { - float StaggerHeavy = 0.6f; - float StaggerModerate = 0.3f; - - float staggerPct = amount / (float)(unit.GetMaxHealth()); - return (staggerPct >= StaggerHeavy) ? SpellIds.StaggerHeavy : - (staggerPct >= StaggerModerate) ? SpellIds.StaggerModerate : - SpellIds.StaggerLight; - } - - void AddNewStagger(Unit unit, uint staggerSpellId, float staggerAmount) - { - // We only set the total stagger amount. The amount per tick will be set by the stagger spell script - unit.CastSpell(unit, staggerSpellId, new CastSpellExtraArgs(SpellValueMod.BasePoint1, (int)staggerAmount).SetTriggerFlags(TriggerCastFlags.FullMask)); + AuraEffect auraEff = auraStagger.GetEffect(1); + if (auraEff != null) + { + float total = (float)auraEff.GetAmount(); + float tickDamage = (float)aurEff.GetAmount(); + auraEff.ChangeAmount((int)(total - tickDamage)); + } } } - [Script] // 124255 - Stagger - SpellIds.StaggerDamageAura - class spell_monk_stagger_damage : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.StaggerLight, SpellIds.StaggerModerate, SpellIds.StaggerHeavy); - } + OnEffectPeriodic.Add(new(OnPeriodicDamage, 0, AuraType.PeriodicDamage)); + } +} - void OnPeriodicDamage(AuraEffect aurEff) - { - // Update our light/medium/heavy stagger with the correct stagger amount left - Aura auraStagger = MonkUtility.FindExistingStaggerEffect(GetTarget()); - if (auraStagger != null) - { - AuraEffect auraEff = auraStagger.GetEffect(1); - if (auraEff != null) - { - float total = (float)(auraEff.GetAmount()); - float tickDamage = (float)(aurEff.GetAmount()); - auraEff.ChangeAmount((int)(total - tickDamage)); - } - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(OnPeriodicDamage, 0, AuraType.PeriodicDamage)); - } +[Script] // 124273, 124274, 124275 - Light/Moderate/Heavy Stagger - StaggerLight / StaggerModerate / StaggerHeavy +class spell_monk_stagger_debuff_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StaggerDamageAura) && ValidateSpellEffect((SpellIds.StaggerDamageAura, 0)); } - [Script] // 124273, 124274, 124275 - Light/Moderate/Heavy Stagger - SpellIds.StaggerLight / SpellIds.StaggerModerate / SpellIds.StaggerHeavy - class spell_monk_stagger_debuff : AuraScript + public override bool Load() { - float _period; + _period = (float)Global.SpellMgr.GetSpellInfo(SpellIds.StaggerDamageAura, GetCastDifficulty()).GetEffect(0).ApplyAuraPeriod; + return true; + } - public override bool Validate(SpellInfo spellInfo) + void OnReapply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // Calculate damage per tick + float total = (float)aurEff.GetAmount(); + float perTick = total * _period / (float)GetDuration(); // should be same as GetMaxDuration() Todo: verify + + // Set amount on effect for tooltip + AuraEffect effInfo = GetAura().GetEffect(0); + if (effInfo != null) + effInfo.ChangeAmount((int)perTick); + + // Set amount on damage aura (or cast it if needed) + CastOrChangeTickDamage(perTick); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (mode != AuraEffectHandleModes.Real) + return; + + // Remove damage aura + GetTarget().RemoveAura(SpellIds.StaggerDamageAura); + } + + public override void Register() + { + AfterEffectApply.Add(new(OnReapply, 1, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); + AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } + + float _period = 0.0f; + + void CastOrChangeTickDamage(float tickDamage) + { + Unit unit = GetTarget(); + Aura auraDamage = unit.GetAura(SpellIds.StaggerDamageAura); + if (auraDamage == null) { - return ValidateSpellInfo(SpellIds.StaggerDamageAura) && ValidateSpellEffect((SpellIds.StaggerDamageAura, 0)); + unit.CastSpell(unit, SpellIds.StaggerDamageAura, true); + auraDamage = unit.GetAura(SpellIds.StaggerDamageAura); } - public override bool Load() + if (auraDamage != null) { - _period = (float)(SpellMgr.GetSpellInfo(SpellIds.StaggerDamageAura, GetCastDifficulty()).GetEffect(0).ApplyAuraPeriod); - return true; - } - - void OnReapply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // Calculate damage per tick - float total = (float)(aurEff.GetAmount()); - float perTick = total * _period / (float)(GetDuration()); // should be same as GetMaxDuration() Todo: verify - - // Set amount on effect for tooltip - AuraEffect effInfo = GetAura().GetEffect(0); - if (effInfo != null) - effInfo.ChangeAmount((int)perTick); - - // Set amount on damage aura (or cast it if needed) - CastOrChangeTickDamage(perTick); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (mode != AuraEffectHandleModes.Real) - return; - - // Remove damage aura - GetTarget().RemoveAura(SpellIds.StaggerDamageAura); - } - - public override void Register() - { - AfterEffectApply.Add(new(OnReapply, 1, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); - AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - - void CastOrChangeTickDamage(float tickDamage) - { - Unit unit = GetTarget(); - Aura auraDamage = unit.GetAura(SpellIds.StaggerDamageAura); - if (auraDamage == null) - { - unit.CastSpell(unit, SpellIds.StaggerDamageAura, true); - auraDamage = unit.GetAura(SpellIds.StaggerDamageAura); - } - - if (auraDamage != null) - { - AuraEffect eff = auraDamage.GetEffect(0); - if (eff != null) - eff.ChangeAmount((int)tickDamage); - } + AuraEffect eff = auraDamage.GetEffect(0); + if (eff != null) + eff.ChangeAmount((int)tickDamage); } } } + +[Script] // 116841 - Tiger's Lust +class spell_monk_tigers_lust : SpellScript +{ + void HandleRemoveImpairingAuras(uint effIndex) + { + GetHitUnit().RemoveMovementImpairingAuras(true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleRemoveImpairingAuras, 0, SpellEffectName.ApplyAura)); + } +} diff --git a/Source/Scripts/Spells/Paladin.cs b/Source/Scripts/Spells/Paladin.cs index ccba57911..881ffa995 100644 --- a/Source/Scripts/Spells/Paladin.cs +++ b/Source/Scripts/Spells/Paladin.cs @@ -1,5 +1,5 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Framework.Dynamic; @@ -12,1442 +12,1705 @@ using Game.Spells; using System; using System.Collections.Generic; using System.Linq; -using static Global; -namespace Scripts.Spells.Paladin +namespace Scripts.Spells.Paladin; + +struct SpellIds { - struct SpellIds - { - public const uint ArdentDefenderHeal = 66235; - public const uint ArtOfWarTriggered = 231843; - public const uint AvengersShield = 31935; - public const uint AvengingWrath = 31884; - public const uint BeaconOfLight = 53563; - public const uint BeaconOfLightHeal = 53652; - public const uint BladeOfJustice = 184575; - public const uint BlindingLightEffect = 105421; - public const uint ConcentractionAura = 19746; - public const uint ConsecratedGroundPassive = 204054; - public const uint ConsecratedGroundSlow = 204242; - public const uint Consecration = 26573; - public const uint ConsecrationDamage = 81297; - public const uint ConsecrationProtectionAura = 188370; - public const uint CrusadingStrikesEnergize = 406834; - public const uint DivinePurposeTriggered = 223819; - public const uint DivineSteedHuman = 221883; - public const uint DivineSteedDwarf = 276111; - public const uint DivineSteedDraenei = 221887; - public const uint DivineSteedDarkIronDwarf = 276112; - public const uint DivineSteedBloodelf = 221886; - public const uint DivineSteedTauren = 221885; - public const uint DivineSteedZandalariTroll = 294133; - public const uint DivineSteedLfDraenei = 363608; - public const uint DivineStormDamage = 224239; - public const uint EnduringLight = 40471; - public const uint EnduringJudgement = 40472; - public const uint EyeForAnEyeTriggered = 205202; - public const uint FinalStand = 204077; - public const uint FinalStandEffect = 204079; - public const uint Forbearance = 25771; - public const uint GuardianOfAncientKings = 86659; - public const uint HammerOfJustice = 853; - public const uint HammerOfTheRighteousAoe = 88263; - public const uint HandOfSacrifice = 6940; - public const uint HolyMending = 64891; - public const uint HolyPowerArmor = 28790; - public const uint HolyPowerAttackPower = 28791; - public const uint HolyPowerSpellPower = 28793; - public const uint HolyPowerMp5 = 28795; - public const uint HolyPrismAreaBeamVisual = 121551; - public const uint HolyPrismTargetAlly = 114871; - public const uint HolyPrismTargetEnemy = 114852; - public const uint HolyPrismTargetBeamVisual = 114862; - public const uint HolyShock = 20473; - public const uint HolyShockDamage = 25912; - public const uint HolyShockHealing = 25914; - public const uint HolyLight = 82326; - public const uint InfusionOfLightEnergize = 356717; - public const uint ImmuneShieldMarker = 61988; - public const uint ItemHealingTrance = 37706; - public const uint JudgmentGainHolyPower = 220637; - public const uint JudgmentHolyR3 = 231644; - public const uint JudgmentHolyR3Debuff = 214222; - public const uint JudgmentProtRetR3 = 315867; - public const uint LightHammerCosmetic = 122257; - public const uint LightHammerDamage = 114919; - public const uint LightHammerHealing = 119952; - public const uint LightHammerPeriodic = 114918; - public const uint RighteousDefenseTaunt = 31790; - public const uint RighteousVerdictAura = 267611; - public const uint SealOfRighteousness = 25742; - public const uint ShieldOfTheRightrousArmor = 132403; - public const uint ShieldOfVengeanceDamage = 184689; - public const uint TemplarVerdictDamage = 224266; - public const uint T302PHeartfireDamage = 408399; - public const uint T302PHeartfireHeal = 408400; - public const uint ZealAura = 269571; + public const uint AJustRewardHeal = 469413; + public const uint ArdentDefenderHeal = 66235; + public const uint ArtOfWarTriggered = 231843; + public const uint AvengersShield = 31935; + public const uint AvengingWrath = 31884; + public const uint BeaconOfLight = 53563; + public const uint BeaconOfLightHeal = 53652; + public const uint BladeOfJustice = 184575; + public const uint BladeOfVengeance = 403826; + public const uint BlessingOfFreedom = 1044; + public const uint BlindingLightEffect = 105421; + public const uint ConcentractionAura = 19746; + public const uint ConsecratedGroundPassive = 204054; + public const uint ConsecratedGroundSlow = 204242; + public const uint Consecration = 26573; + public const uint ConsecrationDamage = 81297; + public const uint ConsecrationProtectionAura = 188370; + public const uint CrusadingStrikesEnergize = 406834; + public const uint DivineAuxiliaryEnergize = 408386; + public const uint DivineAuxiliaryTalent = 406158; + public const uint DivinePurposeTriggered = 223819; + public const uint DivineSteedHuman = 221883; + public const uint DivineSteedDwarf = 276111; + public const uint DivineSteedDraenei = 221887; + public const uint DivineSteedDarkIronDwarf = 276112; + public const uint DivineSteedBloodelf = 221886; + public const uint DivineSteedTauren = 221885; + public const uint DivineSteedZandalariTroll = 294133; + public const uint DivineSteedLfDraenei = 363608; + public const uint DivineStormDamage = 224239; + public const uint EnduringLight = 40471; + public const uint EnduringJudgement = 40472; + public const uint ExecutionSentenceDamage = 387113; + public const uint ExecutionSentence11_Seconds = 406919; + public const uint ExecutionSentence8_Seconds = 386579; + public const uint ExecutionersWill = 406940; + public const uint EyeForAnEyeTriggered = 205202; + public const uint FinalStand = 204077; + public const uint FinalStandEffect = 204079; + public const uint FinalVerdict = 383329; + public const uint Forbearance = 25771; + public const uint GuardianOfAncientKings = 86659; + public const uint HammerOfJustice = 853; + public const uint HammerOfTheRighteousAoe = 88263; + public const uint HandOfSacrifice = 6940; + public const uint HolyMending = 64891; + public const uint HolyPowerArmor = 28790; + public const uint HolyPowerAttackPower = 28791; + public const uint HolyPowerSpellPower = 28793; + public const uint HolyPowerMP5 = 28795; + public const uint HolyPrismAreaBeamVisual = 121551; + public const uint HolyPrismTargetAlly = 114871; + public const uint HolyPrismTargetEnemy = 114852; + public const uint HolyPrismTargetBeamVisual = 114862; + public const uint HolyShock = 20473; + public const uint HolyShockDamage = 25912; + public const uint HolyShockHealing = 25914; + public const uint HolyLight = 82326; + public const uint InfusionOfLightEnergize = 356717; + public const uint ImmuneShieldMarker = 61988; // Serverside + public const uint ItemHealingTrance = 37706; + public const uint JudgmentGainHolyPower = 220637; + public const uint JudgmentHolyR3 = 231644; + public const uint JudgmentHolyR3_Debuff = 214222; + public const uint JudgmentProtRetR3 = 315867; + public const uint LightHammerCosmetic = 122257; + public const uint LightHammerDamage = 114919; + public const uint LightHammerHealing = 119952; + public const uint LightHammerPeriodic = 114918; + public const uint RighteousDefenseTaunt = 31790; + public const uint RighteousVerdictAura = 267611; + public const uint SealOfRighteousness = 25742; + public const uint ShieldOfTheRighteousArmor = 132403; + public const uint ShieldOfVengeanceDamage = 184689; + public const uint TemplarVerdictDamage = 224266; + public const uint T30_2PHeartfireDamage = 408399; + public const uint T30_2PHeartfireHeal = 408400; + public const uint WakeOfAshesStun = 255941; + public const uint ZealAura = 269571; - public const uint AshenHallow = 316958; - public const uint AshenHallowDamage = 317221; - public const uint AshenHallowHeal = 317223; - public const uint AshenHallowAllowHammer = 330382; + //CovenantSpells + public const uint AshenHallow = 316958; + public const uint AshenHallowDamage = 317221; + public const uint AshenHallowHeal = 317223; + public const uint AshenHallowAllowHammer = 330382; + + public const uint VisualKitDivineStorm = 73892; + public const uint VisualSpellHolyShockDamage = 83731; + public const uint VisualSpellHolyShockDamageCrit = 83881; + public const uint VisualSpellHolyShockHeal = 83732; + public const uint VisualSpellHolyShockHealCrit = 83880; + + public const uint LabelPaladinT30_2PHeartfire = 2598; +} + +[Script] // 469411 - A Just Reward +class spell_pal_a_just_reward : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AJustRewardHeal); } - [Script] // 31850 - Ardent Defender - class spell_pal_ardent_defender : AuraScript + static void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.AJustRewardHeal, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.ArdentDefenderHeal) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 31850 - Ardent Defender +class spell_pal_ardent_defender : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ArdentDefenderHeal) && ValidateSpellEffect((spellInfo.Id, 1)); + } + + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + PreventDefaultAction(); + + int targetHealthPercent = GetEffectInfo(1).CalcValue(GetTarget()); + ulong targetHealth = GetTarget().CountPctFromMaxHealth(targetHealthPercent); + if (GetTarget().HealthBelowPct(targetHealthPercent)) + { + // we are currently below desired health + // absorb everything and heal up + GetTarget().CastSpell(GetTarget(), SpellIds.ArdentDefenderHeal, + new CastSpellExtraArgs(aurEff) + .AddSpellMod(SpellValueMod.BasePoint0, (int)(targetHealth - GetTarget().GetHealth()))); + } + else + { + // we are currently above desired health + // just absorb enough to reach that percentage + absorbAmount = (uint)(dmgInfo.GetDamage() - (GetTarget().GetHealth() - targetHealth)); } - void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + Remove(); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(HandleAbsorb, 2)); + } +} + +[Script] // 267344 - Art of War +class spell_pal_art_of_war : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ArtOfWarTriggered, SpellIds.BladeOfJustice); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ResetCooldown(SpellIds.BladeOfJustice, true); + GetTarget().CastSpell(GetTarget(), SpellIds.ArtOfWarTriggered, TriggerCastFlags.IgnoreCastInProgress); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 19042 - Ashen Hallow +class areatrigger_pal_ashen_hallow(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TimeSpan _refreshTimer; + TimeSpan _period; + + void RefreshPeriod() + { + Unit caster = at.GetCaster(); + if (caster != null) { - PreventDefaultAction(); + AuraEffect ashen = caster.GetAuraEffect(SpellIds.AshenHallow, 1); + if (ashen != null) + _period = TimeSpan.FromSeconds(ashen.GetPeriod()); + } + } - int targetHealthPercent = GetEffectInfo(1).CalcValue(GetTarget()); - ulong targetHealth = (ulong)GetTarget().CountPctFromMaxHealth(targetHealthPercent); - if (GetTarget().HealthBelowPct(targetHealthPercent)) + public override void OnCreate(Spell creatingSpell) + { + RefreshPeriod(); + _refreshTimer = _period; + } + + public override void OnUpdate(uint diff) + { + _refreshTimer -= TimeSpan.FromSeconds(diff); + + while (_refreshTimer <= TimeSpan.Zero) + { + Unit caster = at.GetCaster(); + if (caster != null) { - // we are currently below desired health - // absorb everything and heal up - GetTarget().CastSpell(GetTarget(), SpellIds.ArdentDefenderHeal, - new CastSpellExtraArgs(aurEff) - .AddSpellMod(SpellValueMod.BasePoint0, (int)(targetHealth - GetTarget().GetHealth()))); - } - else - { - // we are currently above desired health - // just absorb enough to reach that percentage - absorbAmount = (uint)(dmgInfo.GetDamage() - (int)(GetTarget().GetHealth() - targetHealth)); + caster.CastSpell(at.GetPosition(), SpellIds.AshenHallowHeal); + caster.CastSpell(at.GetPosition(), SpellIds.AshenHallowDamage); } + RefreshPeriod(); + + _refreshTimer += _period; + } + } + + public override void OnUnitEnter(Unit unit) + { + if (unit.GetGUID() == at.GetCasterGUID()) + unit.CastSpell(unit, SpellIds.AshenHallowAllowHammer, true); + } + + public override void OnUnitExit(Unit unit) + { + if (unit.GetGUID() == at.GetCasterGUID()) + unit.RemoveAura(SpellIds.AshenHallowAllowHammer); + } +} + +[Script] // 248033 - Awakening +class spell_pal_awakening : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AvengingWrath) + && ValidateSpellEffect((spellInfo.Id, 1)); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + TimeSpan extraDuration = TimeSpan.FromSeconds(0); + AuraEffect durationEffect = GetEffect(1); + if (durationEffect != null) + extraDuration = TimeSpan.FromSeconds(durationEffect.GetAmount()); + + Aura avengingWrath = GetTarget().GetAura(SpellIds.AvengingWrath); + if (avengingWrath != null) + { + avengingWrath.SetDuration((int)(avengingWrath.GetDuration() + extraDuration.TotalMilliseconds)); + avengingWrath.SetMaxDuration((int)(avengingWrath.GetMaxDuration() + extraDuration.TotalMilliseconds)); + } + else + GetTarget().CastSpell(GetTarget(), SpellIds.AvengingWrath, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.IgnoreSpellAndCategoryCD) + .SetTriggeringSpell(eventInfo.GetProcSpell()) + .AddSpellMod(SpellValueMod.Duration, (int)extraDuration.TotalMilliseconds)); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // Called by 184575 - Blade of Justice +class spell_pal_blade_of_vengeance : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BladeOfVengeance) + && ValidateSpellEffect((spellInfo.Id, 2)) + && spellInfo.GetEffect(2).IsEffect(SpellEffectName.TriggerSpell); + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.BladeOfVengeance); + } + + static void PreventProc(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(PreventProc, 2, Targets.UnitTargetEnemy)); + } +} + +[Script] // 404358 - Blade of Justice +class spell_pal_blade_of_vengeance_aoe_target_selector : SpellScript +{ + void RemoveExplicitTarget(List targets) + { + targets.Remove(GetExplTargetWorldObject()); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(RemoveExplicitTarget, 0, Targets.UnitDestAreaEnemy)); + } +} + +// 1022 - Blessing of Protection +[Script] // 204018 - Blessing of Spellwarding +class spell_pal_blessing_of_protection : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Forbearance, SpellIds.ImmuneShieldMarker) && spellInfo.ExcludeTargetAuraSpell == SpellIds.ImmuneShieldMarker; + } + + void TriggerForbearance() + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.Forbearance, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterHit.Add(new(TriggerForbearance)); + } +} + +[Script] // 115750 - Blinding Light +class spell_pal_blinding_light : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlindingLightEffect); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.BlindingLightEffect, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 26573 - Consecration +class spell_pal_consecration : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo + (SpellIds.ConsecrationDamage, + // validate for areatrigger_pal_consecration + SpellIds.ConsecrationProtectionAura, + SpellIds.ConsecratedGroundPassive, + SpellIds.ConsecratedGroundSlow + ); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + AreaTrigger at = GetTarget().GetAreaTrigger(SpellIds.Consecration); + if (at != null) + GetTarget().CastSpell(at.GetPosition(), SpellIds.ConsecrationDamage); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +// 26573 - Consecration +[Script] // 9228 - AreaTriggerId +class areatrigger_pal_consecration(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + // 243597 is also being cast as protection, but CreateObject is not sent, either serverside areatrigger for this aura or unused - also no visual is seen + if (unit == caster && caster.IsPlayer() && caster.ToPlayer().GetPrimarySpecialization() == ChrSpecialization.PaladinProtection) + caster.CastSpell(caster, SpellIds.ConsecrationProtectionAura); + + if (caster.IsValidAttackTarget(unit)) + if (caster.HasAura(SpellIds.ConsecratedGroundPassive)) + caster.CastSpell(unit, SpellIds.ConsecratedGroundSlow); + } + } + + public override void OnUnitExit(Unit unit) + { + if (at.GetCasterGUID() == unit.GetGUID()) + unit.RemoveAurasDueToSpell(SpellIds.ConsecrationProtectionAura, at.GetCasterGUID()); + + unit.RemoveAurasDueToSpell(SpellIds.ConsecratedGroundSlow, at.GetCasterGUID()); + } +} + +[Script] // 196926 - Crusader Might +class spell_pal_crusader_might : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HolyShock); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.HolyShock, TimeSpan.FromSeconds(aurEff.GetAmount())); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 406833 - Crusading Strikes +class spell_pal_crusading_strikes : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CrusadingStrikesEnergize); + } + + void HandleEffectProc(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetStackAmount() == 2) + { + GetTarget().CastSpell(GetTarget(), SpellIds.CrusadingStrikesEnergize, aurEff); + + // this spell has weird proc order dependency set up in db2 data so we do removal manually Remove(); } - - public override void Register() - { - OnEffectAbsorb.Add(new(HandleAbsorb, 2)); - } } - [Script] // 267344 - Art of War - class spell_pal_art_of_war : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ArtOfWarTriggered, SpellIds.BladeOfJustice); - } + AfterEffectApply.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.RealOrReapplyMask)); + } +} - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(aurEff.GetAmount()); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().GetSpellHistory().ResetCooldown(SpellIds.BladeOfJustice, true); - GetTarget().CastSpell(GetTarget(), SpellIds.ArtOfWarTriggered, TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 406158 - Divine Auxiliary (attached to 343721 - Final Reckoning and 343527 - Execution Sentence) +class spell_pal_divine_auxiliary : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DivineAuxiliaryEnergize, SpellIds.DivineAuxiliaryTalent); } - [Script] // 19042 - Ashen Hallow - class areatrigger_pal_ashen_hallow : AreaTriggerAI + public override bool Load() { - TimeSpan _refreshTimer; - TimeSpan _period; - - public areatrigger_pal_ashen_hallow(AreaTrigger areatrigger) : base(areatrigger) { } - - void RefreshPeriod() - { - Unit caster = at.GetCaster(); - if (caster != null) - { - AuraEffect ashen = caster.GetAuraEffect(SpellIds.AshenHallow, 1); - if (ashen != null) - _period = TimeSpan.FromMilliseconds(ashen.GetPeriod()); - } - } - - public override void OnCreate(Spell creatingSpell) - { - RefreshPeriod(); - _refreshTimer = _period; - } - - public override void OnUpdate(uint diff) - { - _refreshTimer -= TimeSpan.FromMilliseconds(diff); - - while (_refreshTimer <= TimeSpan.FromSeconds(0)) - { - Unit caster = at.GetCaster(); - if (caster != null) - { - caster.CastSpell(at.GetPosition(), SpellIds.AshenHallowHeal); - caster.CastSpell(at.GetPosition(), SpellIds.AshenHallowDamage); - } - - RefreshPeriod(); - - _refreshTimer += _period; - } - } - - public override void OnUnitEnter(Unit unit) - { - if (unit.GetGUID() == at.GetCasterGuid()) - unit.CastSpell(unit, SpellIds.AshenHallowAllowHammer, true); - } - - public override void OnUnitExit(Unit unit) - { - if (unit.GetGUID() == at.GetCasterGuid()) - unit.RemoveAura(SpellIds.AshenHallowAllowHammer); - } + return GetCaster().HasAura(SpellIds.DivineAuxiliaryTalent); } - [Script] // 248033 - Awakening - class spell_pal_awakening : AuraScript + void HandleEnergize() { - public override bool Validate(SpellInfo spellInfo) + Unit caster = GetCaster(); + caster.CastSpell(caster, SpellIds.DivineAuxiliaryEnergize, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.AvengingWrath) - && ValidateSpellEffect((spellInfo.Id, 1)); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(aurEff.GetAmount()); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - TimeSpan extraDuration = TimeSpan.FromMilliseconds(0); - AuraEffect durationEffect = GetEffect(1); - if (durationEffect != null) - extraDuration = TimeSpan.FromSeconds(durationEffect.GetAmount()); - - Aura avengingWrath = GetTarget().GetAura(SpellIds.AvengingWrath); - if (avengingWrath != null) - { - avengingWrath.SetDuration(avengingWrath.GetDuration() + (int)extraDuration.TotalMilliseconds); - avengingWrath.SetMaxDuration(avengingWrath.GetMaxDuration() + (int)extraDuration.TotalMilliseconds); - } - else - GetTarget().CastSpell(GetTarget(), SpellIds.AvengingWrath, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.IgnoreSpellAndCategoryCD) - .SetTriggeringSpell(eventInfo.GetProcSpell()) - .AddSpellMod(SpellValueMod.Duration, (int)extraDuration.TotalMilliseconds)); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } - // 1022 - Blessing of Protection - [Script] // 204018 - Blessing of Spellwarding - class spell_pal_blessing_of_protection : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Forbearance, SpellIds.ImmuneShieldMarker) && spellInfo.ExcludeTargetAuraSpell == SpellIds.ImmuneShieldMarker; - } + AfterCast.Add(new(HandleEnergize)); + } +} - SpellCastResult CheckForbearance() - { - Unit target = GetExplTargetUnit(); - if (target == null || target.HasAura(SpellIds.Forbearance)) - return SpellCastResult.TargetAurastate; - - return SpellCastResult.SpellCastOk; - } - - void TriggerForbearance() - { - Unit target = GetHitUnit(); - if (target != null) - { - GetCaster().CastSpell(target, SpellIds.Forbearance, true); - GetCaster().CastSpell(target, SpellIds.ImmuneShieldMarker, true); - } - } - - public override void Register() - { - OnCheckCast.Add(new(CheckForbearance)); - AfterHit.Add(new(TriggerForbearance)); - } +[Script] // 223817 - Divine Purpose +class spell_pal_divine_purpose : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DivinePurposeTriggered); } - [Script] // 115750 - Blinding Light - class spell_pal_blinding_light : SpellScript + bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlindingLightEffect); - } - - void HandleDummy(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - GetCaster().CastSpell(target, SpellIds.BlindingLightEffect, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ApplyAura)); - } - } - - [Script] // 26573 - Consecration - class spell_pal_consecration : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ConsecrationDamage, SpellIds.ConsecrationProtectionAura, SpellIds.ConsecratedGroundPassive, SpellIds.ConsecratedGroundSlow); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - AreaTrigger at = GetTarget().GetAreaTrigger(SpellIds.Consecration); - if (at != null) - GetTarget().CastSpell(at.GetPosition(), SpellIds.ConsecrationDamage); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } - } - - // 26573 - Consecration - [Script] // 9228 - AreaTriggerId - class areatrigger_pal_consecration : AreaTriggerAI - { - public areatrigger_pal_consecration(AreaTrigger areatrigger) : base(areatrigger) { } - - public override void OnUnitEnter(Unit unit) - { - Unit caster = at.GetCaster(); - if (caster != null) - { - // 243597 is also being cast as protection, but CreateObject is not sent, either serverside areatrigger for this aura or unused - also no visual is seen - if (unit == caster && caster.IsPlayer() && caster.ToPlayer().GetPrimarySpecialization() == ChrSpecialization.PaladinProtection) - caster.CastSpell(caster, SpellIds.ConsecrationProtectionAura); - - if (caster.IsValidAttackTarget(unit)) - if (caster.HasAura(SpellIds.ConsecratedGroundPassive)) - caster.CastSpell(unit, SpellIds.ConsecratedGroundSlow); - } - } - - public override void OnUnitExit(Unit unit) - { - if (at.GetCasterGuid() == unit.GetGUID()) - unit.RemoveAurasDueToSpell(SpellIds.ConsecrationProtectionAura, at.GetCasterGuid()); - - unit.RemoveAurasDueToSpell(SpellIds.ConsecratedGroundSlow, at.GetCasterGuid()); - } - } - - [Script] // 196926 - Crusader Might - class spell_pal_crusader_might : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HolyShock); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.HolyShock, TimeSpan.FromMilliseconds(aurEff.GetAmount())); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - [Script] // 406833 - Crusading Strikes - class spell_pal_crusading_strikes : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CrusadingStrikesEnergize); - } - - void HandleEffectProc(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetStackAmount() == 2) - { - GetTarget().CastSpell(GetTarget(), SpellIds.CrusadingStrikesEnergize, aurEff); - - // this spell has weird proc order dependency set up in db2 data so we do removal manually - Remove(); - } - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell, AuraEffectHandleModes.RealOrReapplyMask)); - } - } - - [Script] // 223817 - Divine Purpose - class spell_pal_divine_purpose : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DivinePurposeTriggered); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell == null) - return false; - - if (!procSpell.HasPowerTypeCost(PowerType.HolyPower)) - return false; - - return RandomHelper.randChance(aurEff.GetAmount()); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.DivinePurposeTriggered, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(eventInfo.GetProcSpell())); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 642 - Divine Shield - class spell_pal_divine_shield : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FinalStand, SpellIds.FinalStandEffect, SpellIds.Forbearance, SpellIds.ImmuneShieldMarker) && spellInfo.ExcludeCasterAuraSpell == SpellIds.ImmuneShieldMarker; - } - - SpellCastResult CheckForbearance() - { - if (GetCaster().HasAura(SpellIds.Forbearance)) - return SpellCastResult.TargetAurastate; - - return SpellCastResult.SpellCastOk; - } - - void HandleFinalStand() - { - if (GetCaster().HasAura(SpellIds.FinalStand)) - GetCaster().CastSpell(null, SpellIds.FinalStandEffect, true); - } - - void TriggerForbearance() - { - Unit caster = GetCaster(); - caster.CastSpell(caster, SpellIds.Forbearance, true); - caster.CastSpell(caster, SpellIds.ImmuneShieldMarker, true); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckForbearance)); - AfterCast.Add(new(HandleFinalStand)); - AfterCast.Add(new(TriggerForbearance)); - } - } - - [Script] // 190784 - Divine Steed - class spell_pal_divine_steed : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DivineSteedHuman, SpellIds.DivineSteedDwarf, SpellIds.DivineSteedDraenei, SpellIds.DivineSteedDarkIronDwarf, - SpellIds.DivineSteedBloodelf, SpellIds.DivineSteedTauren, SpellIds.DivineSteedZandalariTroll, SpellIds.DivineSteedLfDraenei); - } - - void HandleOnCast() - { - Unit caster = GetCaster(); - - uint spellId = caster.GetRace() switch - { - Race.Human => SpellIds.DivineSteedHuman, - Race.Dwarf => SpellIds.DivineSteedDwarf, - Race.Draenei => SpellIds.DivineSteedDraenei, - Race.LightforgedDraenei => SpellIds.DivineSteedLfDraenei, - Race.DarkIronDwarf => SpellIds.DivineSteedDarkIronDwarf, - Race.BloodElf => SpellIds.DivineSteedBloodelf, - Race.Tauren => SpellIds.DivineSteedTauren, - Race.ZandalariTroll => SpellIds.DivineSteedZandalariTroll, - _ => SpellIds.DivineSteedHuman - }; - - caster.CastSpell(caster, spellId, true); - } - - public override void Register() - { - OnCast.Add(new(HandleOnCast)); - } - } - - [Script] // 53385 - Divine Storm - class spell_pal_divine_storm : SpellScript - { - const uint PaladinVisualKitDivineStorm = 73892; - - public override bool Validate(SpellInfo spellInfo) - { - return CliDB.SpellVisualKitStorage.HasRecord(PaladinVisualKitDivineStorm); - } - - void HandleOnCast() - { - GetCaster().SendPlaySpellVisualKit(PaladinVisualKitDivineStorm, 0, 0); - } - - public override void Register() - { - OnCast.Add(new(HandleOnCast)); - } - } - - [Script] // 205191 - Eye for an Eye - class spell_pal_eye_for_an_eye : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EyeForAnEyeTriggered); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().CastSpell(eventInfo.GetActor(), SpellIds.EyeForAnEyeTriggered, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - [Script] // 234299 - Fist of Justice - class spell_pal_fist_of_justice : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HammerOfJustice); - } - - bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell != null) - return procSpell.HasPowerTypeCost(PowerType.HolyPower); - + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) return false; + + if (!procSpell.HasPowerTypeCost(PowerType.HolyPower)) + return false; + + return RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.DivinePurposeTriggered, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(eventInfo.GetProcSpell())); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 642 - Divine Shield +class spell_pal_divine_shield : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FinalStand, SpellIds.FinalStandEffect, SpellIds.Forbearance, SpellIds.ImmuneShieldMarker) + && spellInfo.ExcludeCasterAuraSpell == SpellIds.ImmuneShieldMarker; + } + + void HandleFinalStand() + { + if (GetCaster().HasAura(SpellIds.FinalStand)) + GetCaster().CastSpell(null, SpellIds.FinalStandEffect, true); + } + + void TriggerForbearance() + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.Forbearance, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleFinalStand)); + AfterHit.Add(new(TriggerForbearance)); + } +} + +[Script] // 190784 - Divine Steed +class spell_pal_divine_steed : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DivineSteedHuman, SpellIds.DivineSteedDwarf, SpellIds.DivineSteedDraenei, SpellIds.DivineSteedDarkIronDwarf, SpellIds.DivineSteedBloodelf, + SpellIds.DivineSteedTauren, SpellIds.DivineSteedZandalariTroll, SpellIds.DivineSteedLfDraenei); + } + + void HandleOnCast() + { + Unit caster = GetCaster(); + + uint spellId = SpellIds.DivineSteedHuman; + switch (caster.GetRace()) + { + case Race.Human: + spellId = SpellIds.DivineSteedHuman; + break; + case Race.Dwarf: + spellId = SpellIds.DivineSteedDwarf; + break; + case Race.Draenei: + spellId = SpellIds.DivineSteedDraenei; + break; + case Race.LightforgedDraenei: + spellId = SpellIds.DivineSteedLfDraenei; + break; + case Race.DarkIronDwarf: + spellId = SpellIds.DivineSteedDarkIronDwarf; + break; + case Race.BloodElf: + spellId = SpellIds.DivineSteedBloodelf; + break; + case Race.Tauren: + spellId = SpellIds.DivineSteedTauren; + break; + case Race.ZandalariTroll: + spellId = SpellIds.DivineSteedZandalariTroll; + break; + default: + break; } - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - int value = aurEff.GetAmount() / 10; + caster.CastSpell(caster, spellId, true); + } - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.HammerOfJustice, TimeSpan.FromSeconds(-value)); - } + public override void Register() + { + OnCast.Add(new(HandleOnCast)); + } +} - public override void Register() +[Script] // 53385 - Divine Storm +class spell_pal_divine_storm : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return CliDB.SpellVisualKitStorage.HasRecord(SpellIds.VisualKitDivineStorm); + } + + void HandleOnCast() + { + GetCaster().SendPlaySpellVisualKit(SpellIds.VisualKitDivineStorm, 0, 0); + } + + public override void Register() + { + OnCast.Add(new(HandleOnCast)); + } +} + +[Script] // 343527 - Execution Sentence +class spell_pal_execution_sentence : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ExecutionSentenceDamage, SpellIds.ExecutionersWill, SpellIds.ExecutionSentence11_Seconds, SpellIds.ExecutionSentence8_Seconds); + } + + void HandleVisual(uint effIndex) + { + uint visualSpellId = GetCaster().HasAura(SpellIds.ExecutionersWill) + ? SpellIds.ExecutionSentence11_Seconds + : SpellIds.ExecutionSentence8_Seconds; + GetCaster().CastSpell(GetHitUnit(), visualSpellId, + new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleVisual, 0, SpellEffectName.ApplyAura)); + } +} + +[Script] +class spell_pal_execution_sentence_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)) + && spellInfo.GetEffect(1).IsAura(); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo != null) + aurEff.ChangeAmount((int)(aurEff.GetAmount() + MathFunctions.CalculatePct(damageInfo.GetDamage(), GetEffect(1).GetAmount()))); + } + + void AfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + int amount = aurEff.GetAmount(); + if (amount == 0 || GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.ExecutionSentenceDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, amount) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + AfterEffectRemove.Add(new(AfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 205191 - Eye for an Eye +class spell_pal_eye_for_an_eye : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EyeForAnEyeTriggered); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(eventInfo.GetActor(), SpellIds.EyeForAnEyeTriggered, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 383328 - Final Verdict +class spell_pal_final_verdict : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FinalVerdict); + } + + void HandleDummy(uint effIndex) + { + if (!RandomHelper.randChance(GetEffectValue())) + return; + + Unit caster = GetCaster(); + caster.CastSpell(caster, SpellIds.FinalVerdict, new CastSpellExtraArgs() { - DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); + } +} + +[Script] // 234299 - Fist of Justice +class spell_pal_fist_of_justice : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HammerOfJustice); + } + + bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell != null) + return procSpell.HasPowerTypeCost(PowerType.HolyPower); + + return false; + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + int value = aurEff.GetAmount() / 10; + + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.HammerOfJustice, TimeSpan.FromSeconds(-value)); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // -85043 - Grand Crusader +class spell_pal_grand_crusader : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AvengersShield); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return GetTarget().IsPlayer(); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ResetCooldown(SpellIds.AvengersShield, true); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 54968 - Glyph of Holy Light +class spell_pal_glyph_of_holy_light : SpellScript +{ + void FilterTargets(List targets) + { + uint maxTargets = GetSpellInfo().MaxAffectedTargets; + + if (targets.Count > maxTargets) + { + targets.Sort(new HealthPctOrderPred()); + targets.Resize(maxTargets); } } - [Script] // -85043 - Grand Crusader - class spell_pal_grand_crusader : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AvengersShield); - } + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} - bool CheckProc(ProcEventInfo eventInfo) - { - return GetTarget().IsPlayer(); - } +[Script] // 53595 - Hammer of the Righteous +class spell_pal_hammer_of_the_righteous : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ConsecrationProtectionAura, SpellIds.HammerOfTheRighteousAoe); + } - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().GetSpellHistory().ResetCooldown(SpellIds.AvengersShield, true); - } + void HandleAoEHit(uint effIndex) + { + if (GetCaster().HasAura(SpellIds.ConsecrationProtectionAura)) + GetCaster().CastSpell(GetHitUnit(), SpellIds.HammerOfTheRighteousAoe); + } - public override void Register() + public override void Register() + { + OnEffectHitTarget.Add(new(HandleAoEHit, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 6940 - Hand of Sacrifice +class spell_pal_hand_of_sacrifice : AuraScript +{ + int remainingAmount; + + public override bool Load() + { + Unit caster = GetCaster(); + if (caster != null) { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell)); + remainingAmount = (int)caster.GetMaxHealth(); + return true; + } + return false; + } + + void Split(AuraEffect aurEff, DamageInfo dmgInfo, uint splitAmount) + { + remainingAmount -= (int)splitAmount; + + if (remainingAmount <= 0) + { + GetTarget().RemoveAura(SpellIds.HandOfSacrifice); } } - [Script] // 54968 - Glyph of Holy Light - class spell_pal_glyph_of_holy_light : SpellScript + public override void Register() { - void FilterTargets(List targets) - { - uint maxTargets = GetSpellInfo().MaxAffectedTargets; + OnEffectSplit.Add(new(Split, 0)); + } +} - if (targets.Count > maxTargets) +[Script] // 54149 - Infusion of Light +class spell_pal_infusion_of_light : AuraScript +{ + static FlagArray128 HolyLightSpellClassMask = new(0, 0, 0x400); + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.InfusionOfLightEnergize); + } + + bool CheckFlashOfLightProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcSpell() != null && eventInfo.GetProcSpell().m_appliedMods.Find(p => p == GetAura()) != null; + } + + bool CheckHolyLightProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Paladin, HolyLightSpellClassMask); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.InfusionOfLightEnergize, + new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetTriggeringSpell(eventInfo.GetProcSpell())); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckFlashOfLightProc, 0, AuraType.AddPctModifier)); + DoCheckEffectProc.Add(new(CheckFlashOfLightProc, 2, AuraType.AddFlatModifier)); + + DoCheckEffectProc.Add(new(CheckHolyLightProc, 1, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 327193 - Moment of Glory +class spell_pal_moment_of_glory : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AvengersShield); + } + + void HandleOnHit() + { + GetCaster().GetSpellHistory().ResetCooldown(SpellIds.AvengersShield); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] // 20271/275779/275773 - Judgement (Retribution/Protection/Holy) +class spell_pal_judgment : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.JudgmentProtRetR3, SpellIds.JudgmentGainHolyPower, SpellIds.JudgmentHolyR3, SpellIds.JudgmentHolyR3_Debuff); + } + + void HandleOnHit() + { + Unit caster = GetCaster(); + + if (caster.HasSpell(SpellIds.JudgmentProtRetR3)) + caster.CastSpell(caster, SpellIds.JudgmentGainHolyPower, GetSpell()); + + if (caster.HasSpell(SpellIds.JudgmentHolyR3)) + caster.CastSpell(GetHitUnit(), SpellIds.JudgmentHolyR3_Debuff, GetSpell()); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] // 215661 - Justicar's Vengeance +class spell_pal_justicars_vengeance : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void HandleDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + if (victim.HasUnitState(UnitState.Stunned)) + MathFunctions.AddPct(ref pctMod, GetEffectInfo(1).CalcValue(GetCaster())); + } + + public override void Register() + { + CalcDamage.Add(new(HandleDamage)); + } +} + +[Script] // 114165 - Holy Prism +class spell_pal_holy_prism : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HolyPrismTargetAlly, SpellIds.HolyPrismTargetEnemy, SpellIds.HolyPrismTargetBeamVisual); + } + + void HandleDummy(uint effIndex) + { + if (GetCaster().IsFriendlyTo(GetHitUnit())) + GetCaster().CastSpell(GetHitUnit(), SpellIds.HolyPrismTargetAlly, true); + else + GetCaster().CastSpell(GetHitUnit(), SpellIds.HolyPrismTargetEnemy, true); + + GetCaster().CastSpell(GetHitUnit(), SpellIds.HolyPrismTargetBeamVisual, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// 114852 - Holy Prism (Damage) +[Script] // 114871 - Holy Prism (Heal) +class spell_pal_holy_prism_selector : SpellScript +{ + List _sharedTargets = new(); + ObjectGuid _targetGuid; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HolyPrismTargetAlly, SpellIds.HolyPrismAreaBeamVisual); + } + + void SaveTargetGuid(uint effIndex) + { + _targetGuid = GetHitUnit().GetGUID(); + } + + void FilterTargets(List targets) + { + byte maxTargets = 5; + + if (targets.Count > maxTargets) + { + if (GetSpellInfo().Id == SpellIds.HolyPrismTargetAlly) { targets.Sort(new HealthPctOrderPred()); targets.Resize(maxTargets); } + else + targets.RandomResize(maxTargets); } - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - } + _sharedTargets = targets; } - [Script] // 53595 - Hammer of the Righteous - class spell_pal_hammer_of_the_righteous : SpellScript + void ShareTargets(List targets) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ConsecrationProtectionAura, SpellIds.HammerOfTheRighteousAoe); - } - - void HandleAoEHit(uint effIndex) - { - if (GetCaster().HasAura(SpellIds.ConsecrationProtectionAura)) - GetCaster().CastSpell(GetHitUnit(), SpellIds.HammerOfTheRighteousAoe); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleAoEHit, 0, SpellEffectName.SchoolDamage)); - } + targets.Clear(); + targets.AddRange(_sharedTargets); } - [Script] // 6940 - Hand of Sacrifice - class spell_pal_hand_of_sacrifice : AuraScript + void HandleScript(uint effIndex) { - int remainingAmount; + Unit initialTarget = Global.ObjAccessor.GetUnit(GetCaster(), _targetGuid); + if (initialTarget != null) + initialTarget.CastSpell(GetHitUnit(), SpellIds.HolyPrismAreaBeamVisual, true); + } - public override bool Load() + public override void Register() + { + if (m_scriptSpellId == SpellIds.HolyPrismTargetEnemy) + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaAlly)); + else if (m_scriptSpellId == SpellIds.HolyPrismTargetAlly) + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); + + OnObjectAreaTargetSelect.Add(new(ShareTargets, 2, Targets.UnitDestAreaEntry)); + + OnEffectHitTarget.Add(new(SaveTargetGuid, 0, SpellEffectName.Any)); + OnEffectHitTarget.Add(new(HandleScript, 2, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 20473 - Holy Shock +class spell_pal_holy_shock : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HolyShock, SpellIds.HolyShockHealing, SpellIds.HolyShockDamage); + } + + SpellCastResult CheckCast() + { + Unit caster = GetCaster(); + + Unit target = GetExplTargetUnit(); + if (target != null) { - Unit caster = GetCaster(); - if (caster != null) + if (!caster.IsFriendlyTo(target)) { - remainingAmount = (int)caster.GetMaxHealth(); - return true; + if (!caster.IsValidAttackTarget(target)) + return SpellCastResult.BadTargets; + + if (!caster.IsInFront(target)) + return SpellCastResult.UnitNotInfront; } + } + else + return SpellCastResult.BadTargets; + + return SpellCastResult.SpellCastOk; + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + + Unit unitTarget = GetHitUnit(); + if (unitTarget != null) + { + if (caster.IsFriendlyTo(unitTarget)) + caster.CastSpell(unitTarget, SpellIds.HolyShockHealing, GetSpell()); + else + caster.CastSpell(unitTarget, SpellIds.HolyShockDamage, GetSpell()); + } + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 25912 - Holy Shock +class spell_pal_holy_shock_damage_visual : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return CliDB.SpellVisualStorage.HasRecord(SpellIds.VisualSpellHolyShockDamage) + && CliDB.SpellVisualStorage.HasRecord(SpellIds.VisualSpellHolyShockDamageCrit); + } + + void PlayVisual() + { + GetCaster().SendPlaySpellVisual(GetHitUnit(), IsHitCrit() ? SpellIds.VisualSpellHolyShockDamageCrit : SpellIds.VisualSpellHolyShockDamage, 0, 0, 0.0f, false); + } + + public override void Register() + { + AfterHit.Add(new(PlayVisual)); + } +} + +[Script] // 25914 - Holy Shock +class spell_pal_holy_shock_heal_visual : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return CliDB.SpellVisualStorage.HasRecord(SpellIds.VisualSpellHolyShockHeal) + && CliDB.SpellVisualStorage.HasRecord(SpellIds.VisualSpellHolyShockHealCrit); + } + + void PlayVisual() + { + GetCaster().SendPlaySpellVisual(GetHitUnit(), IsHitCrit() ? SpellIds.VisualSpellHolyShockHealCrit : SpellIds.VisualSpellHolyShockHeal, 0, 0, 0.0f, false); + } + + public override void Register() + { + AfterHit.Add(new(PlayVisual)); + } +} + +[Script] // 37705 - Healing Discount +class spell_pal_item_healing_discount : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ItemHealingTrance); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.ItemHealingTrance, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 40470 - Paladin Tier 6 Trinket +class spell_pal_item_t6_trinket : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EnduringLight, SpellIds.EnduringJudgement); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null) + return; + + uint spellId; + int chance; + + // Holy Light & Flash of Light + if ((spellInfo.SpellFamilyFlags[0] & 0xC0000000) != 0) + { + spellId = SpellIds.EnduringLight; + chance = 15; + } + // Judgements + else if ((spellInfo.SpellFamilyFlags[0] & 0x00800000) != 0) + { + spellId = SpellIds.EnduringJudgement; + chance = 50; + } + else + return; + + if (RandomHelper.randChance(chance)) + eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), spellId, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// 633 - Lay on Hands +[Script] // 471195 - Lay on Hands (from 387791 - Empyreal Ward) +class spell_pal_lay_on_hands : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Forbearance) + && spellInfo.ExcludeTargetAuraSpell == SpellIds.ImmuneShieldMarker; + } + + void TriggerForbearance() + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.Forbearance, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterHit.Add(new(TriggerForbearance)); + } +} + +[Script] // 53651 - Light's Beacon - Beacon of Light +class spell_pal_light_s_beacon : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BeaconOfLight, SpellIds.BeaconOfLightHeal); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetActionTarget() == null) return false; - } - - void Split(AuraEffect aurEff, DamageInfo dmgInfo, uint splitAmount) - { - remainingAmount -= (int)splitAmount; - - if (remainingAmount <= 0) - { - GetTarget().RemoveAura(SpellIds.HandOfSacrifice); - } - } - - public override void Register() - { - OnEffectSplit.Add(new(Split, 0)); - } - } - - [Script] // 54149 - Infusion of Light - class spell_pal_infusion_of_light : AuraScript - { - FlagArray128 HolyLightSpellClassMask = new(0, 0, 0x400); - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.InfusionOfLightEnergize); - } - - bool CheckFlashOfLightProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcSpell() != null && eventInfo.GetProcSpell().m_appliedMods.Contains(GetAura()); - } - - bool CheckHolyLightProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Paladin, HolyLightSpellClassMask); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.InfusionOfLightEnergize, - new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetTriggeringSpell(eventInfo.GetProcSpell())); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckFlashOfLightProc, 0, AuraType.AddPctModifier)); - DoCheckEffectProc.Add(new(CheckFlashOfLightProc, 2, AuraType.AddFlatModifier)); - - DoCheckEffectProc.Add(new(CheckHolyLightProc, 1, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - } - - [Script] // 327193 - Moment of Glory - class spell_pal_moment_of_glory : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AvengersShield); - } - - void HandleOnHit() - { - GetCaster().GetSpellHistory().ResetCooldown(SpellIds.AvengersShield); - } - - public override void Register() - { - OnHit.Add(new(HandleOnHit)); - } - } - - [Script] // 20271/275779/275773 - Judgement (Retribution/Protection/Holy) - class spell_pal_judgment : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.JudgmentProtRetR3, SpellIds.JudgmentGainHolyPower, SpellIds.JudgmentHolyR3, SpellIds.JudgmentHolyR3Debuff); - } - - void HandleOnHit() - { - Unit caster = GetCaster(); - - if (caster.HasSpell(SpellIds.JudgmentProtRetR3)) - caster.CastSpell(caster, SpellIds.JudgmentGainHolyPower, GetSpell()); - - if (caster.HasSpell(SpellIds.JudgmentHolyR3)) - caster.CastSpell(GetHitUnit(), SpellIds.JudgmentHolyR3Debuff, GetSpell()); - } - - public override void Register() - { - OnHit.Add(new(HandleOnHit)); - } - } - - [Script] // 114165 - Holy Prism - class spell_pal_holy_prism : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HolyPrismTargetAlly, SpellIds.HolyPrismTargetEnemy, SpellIds.HolyPrismTargetBeamVisual); - } - - void HandleDummy(uint effIndex) - { - if (GetCaster().IsFriendlyTo(GetHitUnit())) - GetCaster().CastSpell(GetHitUnit(), SpellIds.HolyPrismTargetAlly, true); - else - GetCaster().CastSpell(GetHitUnit(), SpellIds.HolyPrismTargetEnemy, true); - - GetCaster().CastSpell(GetHitUnit(), SpellIds.HolyPrismTargetBeamVisual, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // 114852 - Holy Prism (Damage) - [Script] // 114871 - Holy Prism (Heal) - class spell_pal_holy_prism_selector : SpellScript - { - List _sharedTargets = new(); - ObjectGuid _targetGUID; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HolyPrismTargetAlly, SpellIds.HolyPrismAreaBeamVisual); - } - - void SaveTargetGuid(uint effIndex) - { - _targetGUID = GetHitUnit().GetGUID(); - } - - void FilterTargets(List targets) - { - byte maxTargets = 5; - - if (targets.Count > maxTargets) - { - if (GetSpellInfo().Id == SpellIds.HolyPrismTargetAlly) - { - targets.Sort(new HealthPctOrderPred()); - targets.Resize(maxTargets); - } - else - targets.RandomResize(maxTargets); - } - - _sharedTargets = targets; - } - - void ShareTargets(List targets) - { - targets.Clear(); - targets.AddRange(_sharedTargets); - } - - void HandleScript(uint effIndex) - { - Unit initialTarget = ObjAccessor.GetUnit(GetCaster(), _targetGUID); - if (initialTarget != null) - initialTarget.CastSpell(GetHitUnit(), SpellIds.HolyPrismAreaBeamVisual, true); - } - - public override void Register() - { - if (m_scriptSpellId == SpellIds.HolyPrismTargetEnemy) - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaAlly)); - else if (m_scriptSpellId == SpellIds.HolyPrismTargetAlly) - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); - - OnObjectAreaTargetSelect.Add(new(ShareTargets, 2, Targets.UnitDestAreaEntry)); - - OnEffectHitTarget.Add(new(SaveTargetGuid, 0, SpellEffectName.Any)); - OnEffectHitTarget.Add(new(HandleScript, 2, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 20473 - Holy Shock - class spell_pal_holy_shock : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HolyShock, SpellIds.HolyShockHealing, SpellIds.HolyShockDamage); - } - - SpellCastResult CheckCast() - { - Unit caster = GetCaster(); - - Unit target = GetExplTargetUnit(); - if (target != null) - { - if (!caster.IsFriendlyTo(target)) - { - if (!caster.IsValidAttackTarget(target)) - return SpellCastResult.BadTargets; - - if (!caster.IsInFront(target)) - return SpellCastResult.UnitNotInfront; - } - } - else - return SpellCastResult.BadTargets; - - return SpellCastResult.SpellCastOk; - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - - Unit unitTarget = GetHitUnit(); - if (unitTarget != null) - { - if (caster.IsFriendlyTo(unitTarget)) - caster.CastSpell(unitTarget, SpellIds.HolyShockHealing, GetSpell()); - else - caster.CastSpell(unitTarget, SpellIds.HolyShockDamage, GetSpell()); - } - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 25912 - Holy Shock - class spell_pal_holy_shock_damage_visual : SpellScript - { - const uint PaladinVisualSpellHolyShockDamage = 83731; - const uint PaladinVisualSpellHolyShockDamageCrit = 83881; - - public override bool Validate(SpellInfo spellInfo) - { - return CliDB.SpellVisualStorage.HasRecord(PaladinVisualSpellHolyShockDamage) - && CliDB.SpellVisualStorage.HasRecord(PaladinVisualSpellHolyShockDamageCrit); - } - - void PlayVisual() - { - GetCaster().SendPlaySpellVisual(GetHitUnit(), IsHitCrit() ? PaladinVisualSpellHolyShockDamageCrit : PaladinVisualSpellHolyShockDamage, 0, 0, 0.0f, false); - } - - public override void Register() - { - AfterHit.Add(new(PlayVisual)); - } - } - - [Script] // 25914 - Holy Shock - class spell_pal_holy_shock_heal_visual : SpellScript - { - const uint PaladinVisualSpellHolyShockHeal = 83732; - const uint PaladinVisualSpellHolyShockHealCrit = 83880; - - public override bool Validate(SpellInfo spellInfo) - { - return CliDB.SpellVisualStorage.HasRecord(PaladinVisualSpellHolyShockHeal) - && CliDB.SpellVisualStorage.HasRecord(PaladinVisualSpellHolyShockHealCrit); - } - - void PlayVisual() - { - GetCaster().SendPlaySpellVisual(GetHitUnit(), IsHitCrit() ? PaladinVisualSpellHolyShockHealCrit : PaladinVisualSpellHolyShockHeal, 0, 0, 0.0f, false); - } - - public override void Register() - { - AfterHit.Add(new(PlayVisual)); - } - } - - [Script] // 37705 - Healing Discount - class spell_pal_item_healing_discount : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ItemHealingTrance); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellIds.ItemHealingTrance, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 40470 - Paladin Tier 6 Trinket - class spell_pal_item_t6_trinket : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EnduringLight, SpellIds.EnduringJudgement); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null) - return; - - uint spellId; - int chance; - - // Holy Light & Flash of Light - if ((spellInfo.SpellFamilyFlags[0] & 0xC0000000) != 0) - { - spellId = SpellIds.EnduringLight; - chance = 15; - } - // Judgements - else if ((spellInfo.SpellFamilyFlags[0] & 0x00800000) != 0) - { - spellId = SpellIds.EnduringJudgement; - chance = 50; - } - else - return; - - if (RandomHelper.randChance(chance)) - eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), spellId, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 633 - Lay on Hands - class spell_pal_lay_on_hands : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Forbearance, SpellIds.ImmuneShieldMarker) && spellInfo.ExcludeTargetAuraSpell == SpellIds.ImmuneShieldMarker; - } - - SpellCastResult CheckForbearance() - { - Unit target = GetExplTargetUnit(); - if (target == null || target.HasAura(SpellIds.Forbearance)) - return SpellCastResult.TargetAurastate; - - return SpellCastResult.SpellCastOk; - } - - void TriggerForbearance() - { - Unit target = GetHitUnit(); - if (target != null) - { - GetCaster().CastSpell(target, SpellIds.Forbearance, true); - GetCaster().CastSpell(target, SpellIds.ImmuneShieldMarker, true); - } - } - - public override void Register() - { - OnCheckCast.Add(new(CheckForbearance)); - AfterHit.Add(new(TriggerForbearance)); - } - } - - [Script] // 53651 - Light's Beacon - Beacon of Light - class spell_pal_light_s_beacon : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BeaconOfLight, SpellIds.BeaconOfLightHeal); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - if (eventInfo.GetActionTarget() == null) - return false; - if (eventInfo.GetActionTarget().HasAura(SpellIds.BeaconOfLight, eventInfo.GetActor().GetGUID())) - return false; - return true; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo == null || healInfo.GetHeal() == 0) - return; - - uint heal = MathFunctions.CalculatePct(healInfo.GetHeal(), aurEff.GetAmount()); - - var auras = GetCaster().GetSingleCastAuras(); - foreach (var aura in auras) - { - if (aura.GetId() == SpellIds.BeaconOfLight) - { - List applications = aura.GetApplicationList(); - if (!applications.Empty()) - { - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)heal); - eventInfo.GetActor().CastSpell(applications.FirstOrDefault().GetTarget(), SpellIds.BeaconOfLightHeal, args); - } - return; - } - } - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 122773 - Light's Hammer - class spell_pal_light_hammer_init_summon : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LightHammerCosmetic, SpellIds.LightHammerPeriodic); - } - - void InitSummon() - { - foreach (var summonedObject in GetSpell().GetExecuteLogEffect(SpellEffectName.Summon).GenericVictimTargets) - { - Unit hammer = ObjAccessor.GetUnit(GetCaster(), summonedObject.Victim); - if (hammer != null) - { - hammer.CastSpell(hammer, SpellIds.LightHammerCosmetic, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(GetSpell())); - hammer.CastSpell(hammer, SpellIds.LightHammerPeriodic, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(GetSpell())); - } - } - } - - public override void Register() - { - AfterCast.Add(new(InitSummon)); - } - } - - [Script] // 114918 - Light's Hammer (Periodic) - class spell_pal_light_hammer_periodic : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LightHammerHealing, SpellIds.LightHammerDamage); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - Unit lightHammer = GetTarget(); - Unit originalCaster = lightHammer.GetOwner(); - if (originalCaster != null) - { - originalCaster.CastSpell(lightHammer.GetPosition(), SpellIds.LightHammerDamage, TriggerCastFlags.IgnoreCastInProgress); - originalCaster.CastSpell(lightHammer.GetPosition(), SpellIds.LightHammerHealing, TriggerCastFlags.IgnoreCastInProgress); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } - } - - [Script] // 204074 - Righteous Protector - class spell_pal_righteous_protector : AuraScript - { - SpellPowerCost _baseHolyPowerCost; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AvengingWrath, SpellIds.GuardianOfAncientKings); - } - - bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - SpellInfo procSpell = eventInfo.GetSpellInfo(); - if (procSpell != null) - _baseHolyPowerCost = procSpell.CalcPowerCost(PowerType.HolyPower, false, eventInfo.GetActor(), eventInfo.GetSchoolMask()); - else - _baseHolyPowerCost = null; - - return _baseHolyPowerCost != null; - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - int value = aurEff.GetAmount() * 100 * _baseHolyPowerCost.Amount; - - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.AvengingWrath, TimeSpan.FromMilliseconds(-value)); - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.GuardianOfAncientKings, TimeSpan.FromMilliseconds(-value)); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - [Script] // 267610 - Righteous Verdict - class spell_pal_righteous_verdict : AuraScript - { - public override bool Validate(SpellInfo spellEntry) - { - return ValidateSpellInfo(SpellIds.RighteousVerdictAura); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - procInfo.GetActor().CastSpell(procInfo.GetActor(), SpellIds.RighteousVerdictAura, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - [Script] // 85804 - Selfless Healer - class spell_pal_selfless_healer : AuraScript - { - bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell != null) - return procSpell.HasPowerTypeCost(PowerType.HolyPower); - + if (eventInfo.GetActionTarget().HasAura(SpellIds.BeaconOfLight, eventInfo.GetActor().GetGUID())) return false; - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.ProcTriggerSpell)); - } + return true; } - [Script] // 53600 - Shield of the Righteous - class spell_pal_shield_of_the_righteous : SpellScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + PreventDefaultAction(); + + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo == null || healInfo.GetHeal() == 0) + return; + + uint heal = MathFunctions.CalculatePct(healInfo.GetHeal(), aurEff.GetAmount()); + + var auras = GetCaster().GetSingleCastAuras(); + foreach (var aura in auras) { - return ValidateSpellInfo(SpellIds.ShieldOfTheRightrousArmor); - } - - void HandleArmor() - { - GetCaster().CastSpell(GetCaster(), SpellIds.ShieldOfTheRightrousArmor, true); - } - - public override void Register() - { - AfterCast.Add(new(HandleArmor)); - } - } - - [Script] // 184662 - Shield of Vengeance - class spell_pal_shield_of_vengeance : AuraScript - { - int _initialAmount; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ShieldOfVengeanceDamage) && ValidateSpellEffect((spellInfo.Id, 1)); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - amount = (int)MathFunctions.CalculatePct(GetUnitOwner().GetMaxHealth(), GetEffectInfo(1).CalcValue()); - Player player = GetUnitOwner().ToPlayer(); - if (player != null) - MathFunctions.AddPct(ref amount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone) + player.GetTotalAuraModifier(AuraType.ModVersatility)); - - _initialAmount = amount; - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().CastSpell(GetTarget(), SpellIds.ShieldOfVengeanceDamage, - new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, _initialAmount - aurEff.GetAmount())); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); - OnEffectRemove.Add(new(HandleRemove, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.Real)); - } - } - - [Script] // 85256 - Templar's Verdict - class spell_pal_templar_s_verdict : SpellScript - { - public override bool Validate(SpellInfo spellEntry) - { - return ValidateSpellInfo(SpellIds.TemplarVerdictDamage); - } - - void HandleHitTarget(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.TemplarVerdictDamage, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHitTarget, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 28789 - Holy Power - class spell_pal_t3_6p_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HolyPowerArmor, SpellIds.HolyPowerAttackPower, SpellIds.HolyPowerSpellPower, SpellIds.HolyPowerMp5); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - uint spellId; - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - switch (target.GetClass()) + if (aura.GetId() == SpellIds.BeaconOfLight) { - case Class.Paladin: - case Class.Priest: - case Class.Shaman: - case Class.Druid: - spellId = SpellIds.HolyPowerMp5; - break; - case Class.Mage: - case Class.Warlock: - spellId = SpellIds.HolyPowerSpellPower; - break; - case Class.Hunter: - case Class.Rogue: - spellId = SpellIds.HolyPowerAttackPower; - break; - case Class.Warrior: - spellId = SpellIds.HolyPowerArmor; - break; - default: - return; - } - - caster.CastSpell(target, spellId, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 64890 - Item - Paladin T8 Holy 2P Bonus - class spell_pal_t8_2p_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HolyMending); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo == null || healInfo.GetHeal() == 0) + List applications = aura.GetApplicationList(); + if (!applications.Empty()) + { + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)heal); + eventInfo.GetActor().CastSpell(applications.First().GetTarget(), SpellIds.BeaconOfLightHeal, args); + } return; - - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.HolyMending, GetCastDifficulty()); - int amount = MathFunctions.CalculatePct((int)(healInfo.GetHeal()), aurEff.GetAmount()); - - Cypher.Assert(spellInfo.GetMaxTicks() > 0); - amount /= (int)spellInfo.GetMaxTicks(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(target, SpellIds.HolyMending, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } } } - [Script] // 405547 - Paladin Protection 10.1 Class Set 2pc - class spell_pal_t30_2p_protection_bonus : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.T302PHeartfireDamage); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - PreventDefaultAction(); - - Unit caster = procInfo.GetActor(); - uint ticks = SpellMgr.GetSpellInfo(SpellIds.T302PHeartfireDamage, Difficulty.None).GetMaxTicks(); - uint damage = MathFunctions.CalculatePct(procInfo.GetDamageInfo().GetOriginalDamage(), aurEff.GetAmount()) / ticks; - - caster.CastSpell(procInfo.GetActionTarget(), SpellIds.T302PHeartfireDamage, new CastSpellExtraArgs(aurEff) - .SetTriggeringSpell(procInfo.GetProcSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, (int)damage)); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); } +} - [Script] // 408461 - Heartfire - class spell_pal_t30_2p_protection_bonus_heal : AuraScript +[Script] // 122773 - Light's Hammer +class spell_pal_light_hammer_init_summon : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - const uint SpellLabelPaladinT302PHeartfire = 2598; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.T302PHeartfireHeal); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - return procInfo.GetDamageInfo() != null && procInfo.GetSpellInfo() != null && procInfo.GetSpellInfo().HasLabel(SpellLabelPaladinT302PHeartfire); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - GetTarget().CastSpell(GetTarget(), SpellIds.T302PHeartfireHeal, new CastSpellExtraArgs(aurEff) - .SetTriggeringSpell(procInfo.GetProcSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, (int)procInfo.GetDamageInfo().GetOriginalDamage())); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + return ValidateSpellInfo(SpellIds.LightHammerCosmetic, SpellIds.LightHammerPeriodic); } - [Script] // 269569 - Zeal - class spell_pal_zeal : AuraScript + void InitSummon() { - public override bool Validate(SpellInfo spellInfo) + foreach (var summonedObject in GetSpell().GetExecuteLogEffect(SpellEffectName.Summon).GenericVictimTargets) { - return ValidateSpellInfo(SpellIds.ZealAura); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Unit target = GetTarget(); - target.CastSpell(target, SpellIds.ZealAura, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, aurEff.GetAmount())); - - PreventDefaultAction(); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell)); + Unit hammer = Global.ObjAccessor.GetUnit(GetCaster(), summonedObject.Victim); + if (hammer != null) + { + hammer.CastSpell(hammer, SpellIds.LightHammerCosmetic, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(GetSpell())); + hammer.CastSpell(hammer, SpellIds.LightHammerPeriodic, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(GetSpell())); + } } } -} \ No newline at end of file + + public override void Register() + { + AfterCast.Add(new(InitSummon)); + } +} + +[Script] // 114918 - Light's Hammer (Periodic) +class spell_pal_light_hammer_periodic : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LightHammerHealing, SpellIds.LightHammerDamage); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit lightHammer = GetTarget(); + Unit originalCaster = lightHammer.GetOwner(); + if (originalCaster != null) + { + originalCaster.CastSpell(lightHammer.GetPosition(), SpellIds.LightHammerDamage, TriggerCastFlags.IgnoreCastInProgress); + originalCaster.CastSpell(lightHammer.GetPosition(), SpellIds.LightHammerHealing, TriggerCastFlags.IgnoreCastInProgress); + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 204074 - Righteous Protector +class spell_pal_righteous_protector : AuraScript +{ + SpellPowerCost _baseHolyPowerCost; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AvengingWrath, SpellIds.GuardianOfAncientKings); + } + + bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + SpellInfo procSpell = eventInfo.GetSpellInfo(); + if (procSpell != null) + _baseHolyPowerCost = procSpell.CalcPowerCost(PowerType.HolyPower, false, eventInfo.GetActor(), eventInfo.GetSchoolMask()); + else + _baseHolyPowerCost = null; + + return _baseHolyPowerCost != null; + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + int value = aurEff.GetAmount() * 100 * _baseHolyPowerCost.Amount; + + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.AvengingWrath, TimeSpan.FromSeconds(-value)); + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.GuardianOfAncientKings, TimeSpan.FromSeconds(-value)); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 267610 - Righteous Verdict +class spell_pal_righteous_verdict : AuraScript +{ + public override bool Validate(SpellInfo spellEntry) + { + return ValidateSpellInfo(SpellIds.RighteousVerdictAura); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + procInfo.GetActor().CastSpell(procInfo.GetActor(), SpellIds.RighteousVerdictAura, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 85804 - Selfless Healer +class spell_pal_selfless_healer : AuraScript +{ + bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell != null) + return procSpell.HasPowerTypeCost(PowerType.HolyPower); + + return false; + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 53600 - Shield of the Righteous +class spell_pal_shield_of_the_righteous : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShieldOfTheRighteousArmor); + } + + void HandleArmor() + { + GetCaster().CastSpell(GetCaster(), SpellIds.ShieldOfTheRighteousArmor, true); + } + + public override void Register() + { + AfterCast.Add(new(HandleArmor)); + } +} + +[Script] // 184662 - Shield of Vengeance +class spell_pal_shield_of_vengeance : AuraScript +{ + int _initialAmount = 0; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShieldOfVengeanceDamage) && ValidateSpellEffect((spellInfo.Id, 1)); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + amount = (int)MathFunctions.CalculatePct(GetUnitOwner().GetMaxHealth(), GetEffectInfo(1).CalcValue()); + Player player = GetUnitOwner().ToPlayer(); + if (player != null) + MathFunctions.AddPct(ref amount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone) + player.GetTotalAuraModifier(AuraType.ModVersatility)); + + _initialAmount = amount; + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().CastSpell(GetTarget(), SpellIds.ShieldOfVengeanceDamage, + new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, _initialAmount - aurEff.GetAmount())); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + OnEffectRemove.Add(new(HandleRemove, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.Real)); + } +} + +[Script] // 469304 - Steed of Liberty +class spell_pal_steed_of_liberty : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlessingOfFreedom); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.BlessingOfFreedom, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.Duration, aurEff.GetAmount()) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 85256 - Templar's Verdict +class spell_pal_templar_s_verdict : SpellScript +{ + public override bool Validate(SpellInfo spellEntry) + { + return ValidateSpellInfo(SpellIds.TemplarVerdictDamage); + } + + void HandleHitTarget(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.TemplarVerdictDamage, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHitTarget, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 28789 - Holy Power +class spell_pal_t3_6p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HolyPowerArmor, SpellIds.HolyPowerAttackPower, SpellIds.HolyPowerSpellPower, SpellIds.HolyPowerMP5); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + uint spellId; + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + switch (target.GetClass()) + { + case Class.Paladin: + case Class.Priest: + case Class.Shaman: + case Class.Druid: + spellId = SpellIds.HolyPowerMP5; + break; + case Class.Mage: + case Class.Warlock: + spellId = SpellIds.HolyPowerSpellPower; + break; + case Class.Hunter: + case Class.Rogue: + spellId = SpellIds.HolyPowerAttackPower; + break; + case Class.Warrior: + spellId = SpellIds.HolyPowerArmor; + break; + default: + return; + } + + caster.CastSpell(target, spellId, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 64890 - Item - Paladin T8 Holy 2P Bonus +class spell_pal_t8_2p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HolyMending); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo == null || healInfo.GetHeal() == 0) + return; + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.HolyMending, GetCastDifficulty()); + int amount = MathFunctions.CalculatePct((int)(healInfo.GetHeal()), aurEff.GetAmount()); + + Cypher.Assert(spellInfo.GetMaxTicks() > 0); + amount /= (int)spellInfo.GetMaxTicks(); + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, amount); + caster.CastSpell(target, SpellIds.HolyMending, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 405547 - Paladin Protection 10.1 Class Set 2pc +class spell_pal_t30_2p_protection_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.T30_2PHeartfireDamage); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + PreventDefaultAction(); + + Unit caster = procInfo.GetActor(); + uint ticks = Global.SpellMgr.GetSpellInfo(SpellIds.T30_2PHeartfireDamage, Difficulty.None).GetMaxTicks(); + uint damage = MathFunctions.CalculatePct(procInfo.GetDamageInfo().GetOriginalDamage(), aurEff.GetAmount()) / ticks; + + caster.CastSpell(procInfo.GetActionTarget(), SpellIds.T30_2PHeartfireDamage, new CastSpellExtraArgs(aurEff) + .SetTriggeringSpell(procInfo.GetProcSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, (int)damage)); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 408461 - Heartfire +class spell_pal_t30_2p_protection_bonus_heal : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.T30_2PHeartfireHeal); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + return procInfo.GetDamageInfo() != null && procInfo.GetSpellInfo() != null && procInfo.GetSpellInfo().HasLabel(SpellIds.LabelPaladinT30_2PHeartfire); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + GetTarget().CastSpell(GetTarget(), SpellIds.T30_2PHeartfireHeal, new CastSpellExtraArgs(aurEff) + .SetTriggeringSpell(procInfo.GetProcSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, (int)procInfo.GetDamageInfo().GetOriginalDamage())); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 255937 - Wake of Ashes +class spell_pal_wake_of_ashes : SpellScript +{ + public override bool Validate(SpellInfo spellEntry) + { + return ValidateSpellInfo(SpellIds.WakeOfAshesStun); + } + + void HandleHitTarget(uint effIndex) + { + Unit target = GetHitUnit(); + + if (target.GetCreatureType() == CreatureType.Demon || target.GetCreatureType() == CreatureType.Undead) + { + GetCaster().CastSpell(target, SpellIds.WakeOfAshesStun, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHitTarget, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 269569 - Zeal +class spell_pal_zeal : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ZealAura); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.ZealAura, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.AuraStack, aurEff.GetAmount())); + + PreventDefaultAction(); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.ProcTriggerSpell)); + } +} + diff --git a/Source/Scripts/Spells/Pet.cs b/Source/Scripts/Spells/Pet.cs index 65496bed9..127d3c2ab 100644 --- a/Source/Scripts/Spells/Pet.cs +++ b/Source/Scripts/Spells/Pet.cs @@ -1,1466 +1,197 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +/* + * This file is part of the TrinityCore Project. See Authors file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the Gnu General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but Without + * Any Warranty; without even the implied warranty of Merchantability or + * Fitness For A Particular Purpose. See the Gnu General Public License for + * more details. + * + * You should have received a copy of the Gnu General Public License along + * with this program. If not, see . + */ + +/* + * Scripts for spells with SpellfamilyDeathknight and SpellfamilyGeneric spells used by deathknight players. + * Ordered alphabetically using scriptname. + * Scriptnames of files in this file should be prefixed with "spell_dk_". + */ + using Framework.Constants; -using Game; using Game.Entities; using Game.Scripting; using Game.Spells; -using static Global; -namespace Scripts.Spells.Pets +namespace Scripts.Spells.Pets; + +struct SpellIds { - - struct SpellIds - { - //HunterPetCalculate - public const uint TamedPetPassive06 = 19591; - public const uint TamedPetPassive07 = 20784; - public const uint TamedPetPassive08 = 34666; - public const uint TamedPetPassive09 = 34667; - public const uint TamedPetPassive10 = 34675; - public const uint HunterPetScaling01 = 34902; - public const uint HunterPetScaling02 = 34903; - public const uint HunterPetScaling03 = 34904; - public const uint HunterPetScaling04 = 61017; - public const uint HunterAnimalHandler = 34453; - - //WarlockPetCalculate - public const uint PetPassiveCrit = 35695; - public const uint PetPassiveDamageTaken = 35697; - public const uint WarlockPetScaling01 = 34947; - public const uint WarlockPetScaling02 = 34956; - public const uint WarlockPetScaling03 = 34957; - public const uint WarlockPetScaling04 = 34958; - public const uint WarlockPetScaling05 = 61013; - public const uint WarlockGlyphOfVoidwalker = 56247; - - //DKPetCalculate - public const uint DeathKnightRuneWeapon02 = 51906; - public const uint DeathKnightPetScaling01 = 54566; - public const uint DeathKnightPetScaling02 = 51996; - public const uint DeathKnightPetScaling03 = 61697; - public const uint NightOfTheDead = 55620; - - //ShamanPetCalculate - public const uint FeralSpiritPetUnk01 = 35674; - public const uint FeralSpiritPetUnk02 = 35675; - public const uint FeralSpiritPetUnk03 = 35676; - public const uint FeralSpiritPetScaling04 = 61783; - - //MiscPetCalculate - public const uint MagePetPassiveElemental = 44559; - public const uint PetHealthScaling = 61679; - public const uint PetUnk01 = 67561; - public const uint PetUnk02 = 67557; - } - - struct CreatureIds - { - //WarlockPetCalculate - public const uint EntryFelguard = 17252; - public const uint EntryVoidwalker = 1860; - public const uint EntryFelhunter = 417; - public const uint EntrySuccubus = 1863; - public const uint EntryImp = 416; - - //DKPetCalculate - public const uint EntryArmyOfTheDeadGhoul = 24207; - } - - [Script] - class spell_gen_pet_calculate : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountCritSpell(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float critSpell = 5.0f; - // Increase crit from AuraType.ModSpellCritChance - critSpell += owner.GetTotalAuraModifier(AuraType.ModSpellCritChance); - // Increase crit from AuraType.ModCritPct - critSpell += owner.GetTotalAuraModifier(AuraType.ModCritPct); - // Increase crit spell from spell crit ratings - critSpell += owner.GetRatingBonusValue(CombatRating.CritSpell); - - amount += (int)critSpell; - } - } - - void CalculateAmountCritMelee(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float critMelee = 5.0f; - // Increase crit from AuraType.ModWeaponCritPercent - critMelee += owner.GetTotalAuraModifier(AuraType.ModWeaponCritPercent); - // Increase crit from AuraType.ModCritPct - critMelee += owner.GetTotalAuraModifier(AuraType.ModCritPct); - // Increase crit melee from melee crit ratings - critMelee += owner.GetRatingBonusValue(CombatRating.CritMelee); - - amount += (int)critMelee; - } - } - - void CalculateAmountMeleeHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitMelee = 0.0f; - // Increase hit from AuraType.ModHitChance - hitMelee += owner.GetTotalAuraModifier(AuraType.ModHitChance); - // Increase hit melee from meele hit ratings - hitMelee += owner.GetRatingBonusValue(CombatRating.HitMelee); - - amount += (int)hitMelee; - } - } - - void CalculateAmountSpellHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitSpell = 0.0f; - // Increase hit from AuraType.ModSpellHitChance - hitSpell += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); - // Increase hit spell from spell hit ratings - hitSpell += owner.GetRatingBonusValue(CombatRating.HitSpell); - - amount += (int)hitSpell; - } - } - - void CalculateAmountExpertise(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float expertise = 0.0f; - // Increase hit from AuraType.ModExpertise - expertise += owner.GetTotalAuraModifier(AuraType.ModExpertise); - // Increase Expertise from Expertise ratings - expertise += owner.GetRatingBonusValue(CombatRating.Expertise); - - amount += (int)expertise; - } - } - - public override void Register() - { - switch (m_scriptSpellId) - { - case SpellIds.TamedPetPassive06: - DoEffectCalcAmount.Add(new(CalculateAmountCritMelee, 0, AuraType.ModWeaponCritPercent)); - DoEffectCalcAmount.Add(new(CalculateAmountCritSpell, 1, AuraType.ModSpellCritChance)); - break; - case SpellIds.PetPassiveCrit: - DoEffectCalcAmount.Add(new(CalculateAmountCritSpell, 0, AuraType.ModSpellCritChance)); - DoEffectCalcAmount.Add(new(CalculateAmountCritMelee, 1, AuraType.ModWeaponCritPercent)); - break; - case SpellIds.WarlockPetScaling05: - case SpellIds.HunterPetScaling04: - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountExpertise, 2, AuraType.ModExpertise)); - break; - case SpellIds.DeathKnightPetScaling03: - // case SpellShamanPetHit: - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); - break; - default: - break; - } - } - } - - [Script] - class spell_warl_pet_scaling_01 : AuraScript - { - uint _tempBonus; - - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateStaminaAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - float ownerBonus = MathFunctions.CalculatePct(owner.GetStat(Stats.Stamina), 75); - - amount += (int)ownerBonus; - _tempBonus = (uint)ownerBonus; - } - } - } - - void ApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (_tempBonus != 0) - { - PetLevelInfo pInfo = ObjectMgr.GetPetLevelInfo(pet.GetEntry(), pet.GetLevel()); - uint healthMod; - uint baseHealth = pInfo.health; - switch (pet.GetEntry()) - { - case CreatureIds.EntryImp: - healthMod = (uint)(_tempBonus * 8.4f); - break; - case CreatureIds.EntryFelguard: - case CreatureIds.EntryVoidwalker: - healthMod = _tempBonus * 11; - break; - case CreatureIds.EntrySuccubus: - healthMod = (uint)(_tempBonus * 9.1f); - break; - case CreatureIds.EntryFelhunter: - healthMod = (uint)(_tempBonus * 9.5f); - break; - default: - healthMod = 0; - break; - } - if (healthMod != 0) - pet.ToPet().SetCreateHealth(baseHealth + healthMod); - } - } - } - - void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (pet.IsPet()) - { - PetLevelInfo pInfo = ObjectMgr.GetPetLevelInfo(pet.GetEntry(), pet.GetLevel()); - pet.ToPet().SetCreateHealth(pInfo.health); - } - } - } - - void CalculateAttackPowerAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Player owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int fire = owner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Fire] - owner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Fire]; - int shadow = owner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Shadow] - owner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Shadow]; - int maximum = (fire > shadow) ? fire : shadow; - if (maximum < 0) - maximum = 0; - float bonusAP = maximum * 0.57f; - - amount += (int)bonusAP; - - // Glyph of felguard - if (pet.GetEntry() == CreatureIds.EntryFelguard) - { - AuraEffect aurEffect = owner.GetAuraEffect(56246, 0); - if (aurEffect != null) - { - float base_attPower = pet.GetFlatModifierValue(UnitMods.AttackPower, UnitModifierFlatType.Base) * pet.GetPctModifierValue(UnitMods.AttackPower, UnitModifierPctType.Base); - amount += (int)MathFunctions.CalculatePct(amount + base_attPower, aurEffect.GetAmount()); - } - } - } - } - } - - void CalculateDamageDoneAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Player owner = pet.ToPet().GetOwner(); - if (owner != null) - { - //the damage bonus used for pets is either fire or shadow damage, whatever is higher - int fire = owner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Fire] - owner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Fire]; - int shadow = owner.m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Shadow] - owner.m_activePlayerData.ModDamageDoneNeg[(int)SpellSchools.Shadow]; - int maximum = (fire > shadow) ? fire : shadow; - float bonusDamage = 0.0f; - - if (maximum > 0) - bonusDamage = maximum * 0.15f; - - amount += (int)bonusDamage; - } - } - } - - public override void Register() - { - OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - AfterEffectApply.Add(new(ApplyEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - DoEffectCalcAmount.Add(new(CalculateStaminaAmount, 0, AuraType.ModStat)); - DoEffectCalcAmount.Add(new(CalculateAttackPowerAmount, 1, AuraType.ModAttackPower)); - DoEffectCalcAmount.Add(new(CalculateDamageDoneAmount, 2, AuraType.ModDamageDone)); - } - } - - [Script] - class spell_warl_pet_scaling_02 : AuraScript - { - uint _tempBonus; - - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateIntellectAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int ownerBonus = (int)MathFunctions.CalculatePct(owner.GetStat(Stats.Intellect), 30); - - amount += ownerBonus; - _tempBonus = (uint)ownerBonus; - } - } - - } - - void ApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (_tempBonus != 0) - { - PetLevelInfo pInfo = ObjectMgr.GetPetLevelInfo(pet.GetEntry(), pet.GetLevel()); - uint manaMod; - uint baseMana = pInfo.mana; - switch (pet.GetEntry()) - { - case CreatureIds.EntryImp: - manaMod = (uint)(_tempBonus * 4.9f); - break; - case CreatureIds.EntryVoidwalker: - case CreatureIds.EntrySuccubus: - case CreatureIds.EntryFelhunter: - case CreatureIds.EntryFelguard: - manaMod = (uint)(_tempBonus * 11.5f); - break; - default: - manaMod = 0; - break; - } - if (manaMod != 0) - pet.ToPet().SetCreateMana(baseMana + manaMod); - } - } - } - - void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (pet.IsPet()) - { - PetLevelInfo pInfo = ObjectMgr.GetPetLevelInfo(pet.GetEntry(), pet.GetLevel()); - pet.ToPet().SetCreateMana(pInfo.mana); - } - } - } - - void CalculateArmorAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int ownerBonus = (int)MathFunctions.CalculatePct(owner.GetArmor(), 35); - amount += ownerBonus; - } - } - } - } - - void CalculateFireResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Fire), 40); - amount += ownerBonus; - } - } - } - - public override void Register() - { - OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - AfterEffectApply.Add(new(ApplyEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - DoEffectCalcAmount.Add(new(CalculateIntellectAmount, 0, AuraType.ModStat)); - DoEffectCalcAmount.Add(new(CalculateArmorAmount, 1, AuraType.ModResistance)); - DoEffectCalcAmount.Add(new(CalculateFireResistanceAmount, 2, AuraType.ModResistance)); - } - } - - [Script] - class spell_warl_pet_scaling_03 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateFrostResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Frost), 40); - amount += ownerBonus; - } - } - } - - void CalculateArcaneResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Arcane), 40); - amount += ownerBonus; - } - } - } - - void CalculateNatureResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Nature), 40); - amount += ownerBonus; - } - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateFrostResistanceAmount, 0, AuraType.ModResistance)); - DoEffectCalcAmount.Add(new(CalculateArcaneResistanceAmount, 1, AuraType.ModResistance)); - DoEffectCalcAmount.Add(new(CalculateNatureResistanceAmount, 2, AuraType.ModResistance)); - } - } - - [Script] - class spell_warl_pet_scaling_04 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateShadowResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Shadow), 40); - amount += ownerBonus; - } - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateShadowResistanceAmount, 0, AuraType.ModResistance)); - } - } - - [Script] - class spell_warl_pet_scaling_05 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountMeleeHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitMelee = 0.0f; - // Increase hit from AuraType.ModSpellHitChance - hitMelee += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); - // Increase hit spell from spell hit ratings - hitMelee += owner.GetRatingBonusValue(CombatRating.HitSpell); - - amount += (int)hitMelee; - } - } - - void CalculateAmountSpellHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitSpell = 0.0f; - // Increase hit from AuraType.ModSpellHitChance - hitSpell += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); - // Increase hit spell from spell hit ratings - hitSpell += owner.GetRatingBonusValue(CombatRating.HitSpell); - - amount += (int)hitSpell; - } - } - - void CalculateAmountExpertise(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float expertise = 0.0f; - // Increase hit from AuraType.ModSpellHitChance - expertise += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); - // Increase hit spell from spell hit ratings - expertise += owner.GetRatingBonusValue(CombatRating.HitSpell); - - amount += (int)expertise; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountExpertise, 2, AuraType.ModExpertise)); - } - } - - [Script] - class spell_warl_pet_passive : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountCritSpell(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float CritSpell = 5.0f; - // Increase crit from AuraType.ModSpellCritChance - CritSpell += owner.GetTotalAuraModifier(AuraType.ModSpellCritChance); - // Increase crit from AuraType.ModCritPct - CritSpell += owner.GetTotalAuraModifier(AuraType.ModCritPct); - // Increase crit spell from spell crit ratings - CritSpell += owner.GetRatingBonusValue(CombatRating.CritSpell); - - AuraApplication improvedDemonicTacticsApp = owner.GetAuraApplicationOfRankedSpell(54347); - if (improvedDemonicTacticsApp != null) - { - Aura improvedDemonicTactics = improvedDemonicTacticsApp.GetBase(); - if (improvedDemonicTactics != null) - { - AuraEffect improvedDemonicTacticsEffect = improvedDemonicTactics.GetEffect(0); - if (improvedDemonicTacticsEffect != null) - amount += (int)MathFunctions.CalculatePct(CritSpell, improvedDemonicTacticsEffect.GetAmount()); - } - } - } - } - - void CalculateAmountCritMelee(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float CritMelee = 5.0f; - // Increase crit from AuraType.ModWeaponCritPercent - CritMelee += owner.GetTotalAuraModifier(AuraType.ModWeaponCritPercent); - // Increase crit from AuraType.ModCritPct - CritMelee += owner.GetTotalAuraModifier(AuraType.ModCritPct); - // Increase crit melee from melee crit ratings - CritMelee += owner.GetRatingBonusValue(CombatRating.CritMelee); - - AuraApplication improvedDemonicTacticsApp = owner.GetAuraApplicationOfRankedSpell(54347); - if (improvedDemonicTacticsApp != null) - { - Aura improvedDemonicTactics = improvedDemonicTacticsApp.GetBase(); - if (improvedDemonicTactics != null) - { - AuraEffect improvedDemonicTacticsEffect = improvedDemonicTactics.GetEffect(0); - if (improvedDemonicTacticsEffect != null) - amount += (int)MathFunctions.CalculatePct(CritMelee, improvedDemonicTacticsEffect.GetAmount()); - } - } - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountCritSpell, 0, AuraType.ModSpellCritChance)); - DoEffectCalcAmount.Add(new(CalculateAmountCritMelee, 1, AuraType.ModWeaponCritPercent)); - } - } - - [Script] // this doesnt actually fit in here - class spell_warl_pet_passive_damage_done : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountDamageDone(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - if (GetCaster().GetOwner().ToPlayer() != null) - { - switch (GetCaster().GetEntry()) - { - case CreatureIds.EntryVoidwalker: - amount += -16; - break; - case CreatureIds.EntryFelhunter: - amount += -20; - break; - case CreatureIds.EntrySuccubus: - case CreatureIds.EntryFelguard: - amount += 5; - break; - } - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountDamageDone, 0, AuraType.ModDamagePercentDone)); - DoEffectCalcAmount.Add(new(CalculateAmountDamageDone, 1, AuraType.ModDamagePercentDone)); - } - } - - [Script] - class spell_warl_pet_passive_voidwalker : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null && pet.IsPet()) - { - Unit owner = pet.ToPet().GetOwner(); - if (owner != null) - { - AuraEffect aurEffect = owner.GetAuraEffect(SpellIds.WarlockGlyphOfVoidwalker, 0); - if (aurEffect != null) - amount += aurEffect.GetAmount(); - } - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.ModTotalStatPercentage)); - } - } - - [Script] - class spell_sha_pet_scaling_04 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountMeleeHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitMelee = 0.0f; - // Increase hit from AuraType.ModHitChance - hitMelee += owner.GetTotalAuraModifier(AuraType.ModHitChance); - // Increase hit melee from meele hit ratings - hitMelee += owner.GetRatingBonusValue(CombatRating.HitMelee); - - amount += (int)hitMelee; - } - } - - void CalculateAmountSpellHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitSpell = 0.0f; - // Increase hit from AuraType.ModSpellHitChance - hitSpell += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); - // Increase hit spell from spell hit ratings - hitSpell += owner.GetRatingBonusValue(CombatRating.HitSpell); - - amount += (int)hitSpell; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); - } - } - - [Script] - class spell_hun_pet_scaling_01 : AuraScript - { - uint _tempHealth; - - void CalculateStaminaAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Pet pet = GetUnitOwner()?.ToPet(); - if (pet != null) - { - Unit owner = pet.GetOwner(); - if (owner != null) - { - float mod = 0.45f; - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(62758, GetCastDifficulty()) ?? SpellMgr.GetSpellInfo(62762, GetCastDifficulty()); - if (spellInfo != null) // If pet has Wild Hunt - MathFunctions.AddPct(ref mod, spellInfo.GetEffect(0).CalcValue()); - - amount += (int)(owner.GetStat(Stats.Stamina) * mod); - } - } - } - - void ApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (_tempHealth != 0) - pet.SetHealth(_tempHealth); - } - } - - void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null) - _tempHealth = (uint)pet.GetHealth(); - } - - void CalculateAttackPowerAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - float mod = 1.0f; //Hunter contribution modifier - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(62758, GetCastDifficulty()) ?? SpellMgr.GetSpellInfo(62762, GetCastDifficulty()); - if (spellInfo != null) // If pet has Wild Hunt - mod += MathFunctions.CalculatePct(1.0f, spellInfo.GetEffect(1).CalcValue()); - - amount += (int)(owner.GetTotalAttackPowerValue(WeaponAttackType.RangedAttack) * 0.22f * mod); - } - } - - void CalculateDamageDoneAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - float mod = 1.0f; //Hunter contribution modifier - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(62758, GetCastDifficulty()) ?? SpellMgr.GetSpellInfo(62762, GetCastDifficulty()); - if (spellInfo != null) // If pet has Wild Hunt - mod += MathFunctions.CalculatePct(1.0f, spellInfo.GetEffect(1).CalcValue()); - - amount += (int)(owner.GetTotalAttackPowerValue(WeaponAttackType.RangedAttack) * 0.1287f * mod); - } - } - - public override void Register() - { - OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - AfterEffectApply.Add(new(ApplyEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - DoEffectCalcAmount.Add(new(CalculateStaminaAmount, 0, AuraType.ModStat)); - DoEffectCalcAmount.Add(new(CalculateAttackPowerAmount, 1, AuraType.ModAttackPower)); - DoEffectCalcAmount.Add(new(CalculateDamageDoneAmount, 2, AuraType.ModDamageDone)); - } - } - - [Script] - class spell_hun_pet_scaling_02 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateFrostResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Frost), 40); - amount += ownerBonus; - } - } - - void CalculateFireResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Fire), 40); - amount += ownerBonus; - } - } - - void CalculateNatureResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Nature), 40); - amount += ownerBonus; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateFrostResistanceAmount, 1, AuraType.ModResistance)); - DoEffectCalcAmount.Add(new(CalculateFireResistanceAmount, 0, AuraType.ModResistance)); - DoEffectCalcAmount.Add(new(CalculateNatureResistanceAmount, 2, AuraType.ModResistance)); - } - } - - [Script] - class spell_hun_pet_scaling_03 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateShadowResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Shadow), 40); - amount += ownerBonus; - } - } - - void CalculateArcaneResistanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - int ownerBonus = MathFunctions.CalculatePct(owner.GetResistance(SpellSchoolMask.Arcane), 40); - amount += ownerBonus; - } - } - - void CalculateArmorAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsPet()) - return; - - Unit owner = pet.ToPet().GetOwner(); - if (owner == null) - return; - - amount += (int)MathFunctions.CalculatePct(owner.GetArmor(), 35); - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateShadowResistanceAmount, 0, AuraType.ModResistance)); - DoEffectCalcAmount.Add(new(CalculateArcaneResistanceAmount, 1, AuraType.ModResistance)); - DoEffectCalcAmount.Add(new(CalculateArmorAmount, 2, AuraType.ModResistance)); - } - } - - [Script] - class spell_hun_pet_scaling_04 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountMeleeHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitMelee = 0.0f; - // Increase hit from AuraType.ModHitChance - hitMelee += owner.GetTotalAuraModifier(AuraType.ModHitChance); - // Increase hit melee from meele hit ratings - hitMelee += owner.GetRatingBonusValue(CombatRating.HitMelee); - - amount += (int)hitMelee; - } - } - - void CalculateAmountSpellHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitSpell = 0.0f; - // Increase hit from AuraType.ModSpellHitChance - hitSpell += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); - // Increase hit spell from spell hit ratings - hitSpell += owner.GetRatingBonusValue(CombatRating.HitSpell); - - amount += (int)hitSpell; - } - } - - void CalculateAmountExpertise(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float expertise = 0.0f; - // Increase hit from AuraType.ModExpertise - expertise += owner.GetTotalAuraModifier(AuraType.ModExpertise); - // Increase Expertise from Expertise ratings - expertise += owner.GetRatingBonusValue(CombatRating.Expertise); - - amount += (int)expertise; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountExpertise, 2, AuraType.ModExpertise)); - } - } - - [Script] - class spell_hun_pet_passive_crit : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountCritSpell(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - if (GetCaster().GetOwner().ToPlayer() != null) - { - // For others recalculate it from: - float CritSpell = 5.0f; - // Increase crit from AuraType.ModSpellCritChance - // CritSpell += owner.GetTotalAuraModifier(AuraType.ModSpellCritChance); - // Increase crit from AuraType.ModCritPct - // CritSpell += owner.GetTotalAuraModifier(AuraType.ModCritPct); - // Increase crit spell from spell crit ratings - // CritSpell += owner.GetRatingBonusValue(CrCritSpell); - - amount += (int)(CritSpell * 0.8f); - } - } - - void CalculateAmountCritMelee(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - if (GetCaster().GetOwner().ToPlayer() != null) - { - // For others recalculate it from: - float CritMelee = 5.0f; - // Increase crit from AuraType.ModWeaponCritPercent - // CritMelee += owner.GetTotalAuraModifier(AuraType.ModWeaponCritPercent); - // Increase crit from AuraType.ModCritPct - // CritMelee += owner.GetTotalAuraModifier(AuraType.ModCritPct); - // Increase crit melee from melee crit ratings - // CritMelee += owner.GetRatingBonusValue(CrCritMelee); - - amount += (int)(CritMelee * 0.8f); - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountCritSpell, 1, AuraType.ModSpellCritChance)); - DoEffectCalcAmount.Add(new(CalculateAmountCritMelee, 0, AuraType.ModWeaponCritPercent)); - } - } - - [Script] - class spell_hun_pet_passive_damage_done : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountDamageDone(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - if (GetCaster().GetOwner().ToPlayer() != null) - { - // Cobra Reflexes - AuraEffect cobraReflexes = GetCaster().GetAuraEffectOfRankedSpell(61682, 0); - if (cobraReflexes != null) - amount -= cobraReflexes.GetAmount(); - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountDamageDone, 0, AuraType.ModDamagePercentDone)); - } - } - - [Script] - class spell_hun_animal_handler : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountDamageDone(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - AuraEffect aurEffect = owner.GetAuraEffectOfRankedSpell(SpellIds.HunterAnimalHandler, 1); - if (aurEffect != null) - amount = aurEffect.GetAmount(); - else - amount = 0; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountDamageDone, 0, AuraType.ModAttackPowerPct)); - } - } - - [Script] - class spell_dk_avoidance_passive : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAvoidanceAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - Unit owner = pet.GetOwner(); - if (owner != null) - { - // Army of the dead ghoul - if (pet.GetEntry() == CreatureIds.EntryArmyOfTheDeadGhoul) - amount = -90; - // Night of the dead - else - { - Aura aur = owner.GetAuraOfRankedSpell(SpellIds.NightOfTheDead); - if (aur != null) - amount = aur.GetSpellInfo().GetEffect(2).CalcValue(); - } - } - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAvoidanceAmount, 0, AuraType.ModCreatureAoeDamageAvoidance)); - } - } - - [Script] - class spell_dk_pet_scaling_01 : AuraScript - { - uint _tempHealth; - - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateStaminaAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (pet.IsGuardian()) - { - Unit owner = pet.GetOwner(); - if (owner != null) - { - float ownerBonus = (float)(owner.GetStat(Stats.Stamina)) * 0.3f; - amount += (int)ownerBonus; - } - } - } - } - - void ApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null && _tempHealth != 0) - pet.SetHealth(_tempHealth); - } - - void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit pet = GetUnitOwner(); - if (pet != null) - _tempHealth = (uint)pet.GetHealth(); - } - - void CalculateStrengthAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - if (!pet.IsGuardian()) - return; - - Unit owner = pet.GetOwner(); - if (owner == null) - return; - - float ownerBonus = (float)(owner.GetStat(Stats.Strength)) * 0.7f; - amount += (int)ownerBonus; - } - } - - public override void Register() - { - OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - AfterEffectApply.Add(new(ApplyEffect, 0, AuraType.ModStat, AuraEffectHandleModes.ChangeAmountMask)); - DoEffectCalcAmount.Add(new(CalculateStaminaAmount, 0, AuraType.ModStat)); - DoEffectCalcAmount.Add(new(CalculateStrengthAmount, 1, AuraType.ModStat)); - } - } - - [Script] - class spell_dk_pet_scaling_02 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountMeleeHaste(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hasteMelee = 0.0f; - // Increase hit from AuraType.ModHitChance - hasteMelee += (1 - owner.m_modAttackSpeedPct[(int)WeaponAttackType.BaseAttack]) * 100; - - amount += (int)hasteMelee; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHaste, 1, AuraType.MeleeSlow)); - } - } - - [Script] - class spell_dk_pet_scaling_03 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateAmountMeleeHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitMelee = 0.0f; - // Increase hit from AuraType.ModHitChance - hitMelee += owner.GetTotalAuraModifier(AuraType.ModHitChance); - // Increase hit melee from meele hit ratings - hitMelee += owner.GetRatingBonusValue(CombatRating.HitMelee); - - amount += (int)hitMelee; - } - } - - void CalculateAmountSpellHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hitSpell = 0.0f; - // Increase hit from AuraType.ModSpellHitChance - hitSpell += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); - // Increase hit spell from spell hit ratings - hitSpell += owner.GetRatingBonusValue(CombatRating.HitSpell); - - amount += (int)hitSpell; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); - DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); - } - } - - [Script] - class spell_dk_rune_weapon_scaling_02 : AuraScript - { - public override bool Load() - { - if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) - return false; - return true; - } - - void CalculateDamageDoneAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit pet = GetUnitOwner(); - if (pet != null) - { - Unit owner = pet.GetOwner(); - if (owner == null) - return; - - if (pet.IsGuardian()) - ((Guardian)pet).SetBonusDamage((int)owner.GetTotalAttackPowerValue(WeaponAttackType.BaseAttack)); - - amount += (int)owner.CalculateDamage(WeaponAttackType.BaseAttack, true, true); - } - } - - void CalculateAmountMeleeHaste(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - if (GetCaster() == null || GetCaster().GetOwner() == null) - return; - - Player owner = GetCaster().GetOwner().ToPlayer(); - if (owner != null) - { - // For others recalculate it from: - float hasteMelee = 0.0f; - // Increase hit from AuraType.ModHitChance - hasteMelee += (1 - owner.m_modAttackSpeedPct[(int)WeaponAttackType.BaseAttack]) * 100; - - amount += (int)hasteMelee; - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateDamageDoneAmount, 0, AuraType.ModDamageDone)); - DoEffectCalcAmount.Add(new(CalculateAmountMeleeHaste, 1, AuraType.MeleeSlow)); - } - } + // HunterPetCalculate + public const uint TamedPetPassive06 = 19591; + public const uint TamedPetPassive07 = 20784; + public const uint TamedPetPassive08 = 34666; + public const uint TamedPetPassive09 = 34667; + public const uint TamedPetPassive10 = 34675; + public const uint HunterPetScaling01 = 34902; + public const uint HunterPetScaling02 = 34903; + public const uint HunterPetScaling03 = 34904; + public const uint HunterPetScaling04 = 61017; + public const uint HunterAnimalHandler = 34453; + + // WarlockPetCalculate + public const uint PetPassiveCrit = 35695; + public const uint PetPassiveDamageTaken = 35697; + public const uint WarlockPetScaling01 = 34947; + public const uint WarlockPetScaling02 = 34956; + public const uint WarlockPetScaling03 = 34957; + public const uint WarlockPetScaling04 = 34958; + public const uint WarlockPetScaling05 = 61013; + public const uint WarlockGlyphOfVoidwalker = 56247; + + // DKPetCalculate + public const uint DeathKnightRuneWeapon02 = 51906; + public const uint DeathKnightPetScaling01 = 54566; + public const uint DeathKnightPetScaling02 = 51996; + public const uint DeathKnightPetScaling03 = 61697; + public const uint NightOfTheDead = 55620; + + // ShamanPetCalculate + public const uint FeralSpiritPetUnk01 = 35674; + public const uint FeralSpiritPetUnk02 = 35675; + public const uint FeralSpiritPetUnk03 = 35676; + public const uint FeralSpiritPetScaling04 = 61783; + + // MiscPetCalculate + public const uint MagePetPassiveElemental = 44559; + public const uint PetHealthScaling = 61679; + public const uint PetUnk01 = 67561; + public const uint PetUnk02 = 67557; } + +[Script] +class spell_gen_pet_calculate : AuraScript +{ + public override bool Load() + { + if (GetCaster() == null || GetCaster().GetOwner() == null || !GetCaster().GetOwner().IsPlayer()) + return false; + return true; + } + + void CalculateAmountCritSpell(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player owner = GetCaster().GetOwner().ToPlayer(); + if (owner != null) + { + // For others recalculate it from: + float CritSpell = 5.0f; + // Increase crit from SpellAuraModSpellCritChance + CritSpell += owner.GetTotalAuraModifier(AuraType.ModSpellCritChance); + // Increase crit from SpellAuraModCritPct + CritSpell += owner.GetTotalAuraModifier(AuraType.ModCritPct); + // Increase crit spell from spell crit ratings + CritSpell += owner.GetRatingBonusValue(CombatRating.CritSpell); + + amount += (int)CritSpell; + } + } + + void CalculateAmountCritMelee(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player owner = GetCaster().GetOwner().ToPlayer(); + if (owner != null) + { + // For others recalculate it from: + float CritMelee = 5.0f; + // Increase crit from SpellAuraModWeaponCritPercent + CritMelee += owner.GetTotalAuraModifier(AuraType.ModWeaponCritPercent); + // Increase crit from SpellAuraModCritPct + CritMelee += owner.GetTotalAuraModifier(AuraType.ModCritPct); + // Increase crit melee from melee crit ratings + CritMelee += owner.GetRatingBonusValue(CombatRating.CritMelee); + + amount += (int)CritMelee; + } + } + + void CalculateAmountMeleeHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player owner = GetCaster().GetOwner().ToPlayer(); + if (owner != null) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SpellAuraModHitChance + HitMelee += owner.GetTotalAuraModifier(AuraType.ModHitChance); + // Increase hit melee from meele hit ratings + HitMelee += owner.GetRatingBonusValue(CombatRating.HitMelee); + + amount += (int)HitMelee; + } + } + + void CalculateAmountSpellHit(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player owner = GetCaster().GetOwner().ToPlayer(); + if (owner != null) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SpellAuraModSpellHitChance + HitSpell += owner.GetTotalAuraModifier(AuraType.ModSpellHitChance); + // Increase hit spell from spell hit ratings + HitSpell += owner.GetRatingBonusValue(CombatRating.HitSpell); + + amount += (int)HitSpell; + } + } + + void CalculateAmountExpertise(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Player owner = GetCaster().GetOwner().ToPlayer(); + if (owner != null) + { + // For others recalculate it from: + float Expertise = 0.0f; + // Increase hit from SpellAuraModExpertise + Expertise += owner.GetTotalAuraModifier(AuraType.ModExpertise); + // Increase Expertise from Expertise ratings + Expertise += owner.GetRatingBonusValue(CombatRating.Expertise); + + amount += (int)Expertise; + } + } + + public override void Register() + { + switch (m_scriptSpellId) + { + case SpellIds.TamedPetPassive06: + DoEffectCalcAmount.Add(new(CalculateAmountCritMelee, 0, AuraType.ModWeaponCritPercent)); + DoEffectCalcAmount.Add(new(CalculateAmountCritSpell, 1, AuraType.ModSpellCritChance)); + break; + case SpellIds.PetPassiveCrit: + DoEffectCalcAmount.Add(new(CalculateAmountCritSpell, 0, AuraType.ModSpellCritChance)); + DoEffectCalcAmount.Add(new(CalculateAmountCritMelee, 1, AuraType.ModWeaponCritPercent)); + break; + case SpellIds.WarlockPetScaling05: + case SpellIds.HunterPetScaling04: + DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); + DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); + DoEffectCalcAmount.Add(new(CalculateAmountExpertise, 2, AuraType.ModExpertise)); + break; + case SpellIds.DeathKnightPetScaling03: + // case SpellShamanPetHit: + DoEffectCalcAmount.Add(new(CalculateAmountMeleeHit, 0, AuraType.ModHitChance)); + DoEffectCalcAmount.Add(new(CalculateAmountSpellHit, 1, AuraType.ModSpellHitChance)); + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/Source/Scripts/Spells/Priest.cs b/Source/Scripts/Spells/Priest.cs index 9b34a7062..e873d2d08 100644 --- a/Source/Scripts/Spells/Priest.cs +++ b/Source/Scripts/Spells/Priest.cs @@ -1,7 +1,6 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. -using Bgs.Protocol.Notification.V1; using Framework.Constants; using Framework.Dynamic; using Game.AI; @@ -12,3461 +11,3560 @@ using Game.Spells; using System; using System.Collections.Generic; using System.Linq; -using System.Numerics; -using static Global; -namespace Scripts.Spells.Priest +namespace Scripts.Spells.Priest; + +struct SpellIds { + public const uint AbyssalReverie = 373054; + public const uint AngelicFeatherAreatrigger = 158624; + public const uint AngelicFeatherAura = 121557; + public const uint AnsweredPrayers = 394289; + public const uint Apotheosis = 200183; + public const uint ArmorOfFaith = 28810; + public const uint AssuredSafety = 440766; + public const uint Atonement = 81749; + public const uint AtonementEffect = 194384; + public const uint AtonementHeal = 81751; + public const uint Benediction = 193157; + public const uint Benevolence = 415416; + public const uint BlazeOfLight = 215768; + public const uint BlazeOfLightIncrease = 355851; + public const uint BlazeOfLightDecrease = 356084; + public const uint BlessedHealing = 70772; + public const uint BlessedLight = 196813; + public const uint BodyAndSoul = 64129; + public const uint BodyAndSoulSpeed = 65081; + public const uint CircleOfHealing = 204883; + public const uint CrystallineReflection = 373457; + public const uint CrystallineReflectionHeal = 373462; + public const uint CrystallineReflectionReflect = 373464; + public const uint DarkIndulgence = 372972; + public const uint DarkReprimand = 400169; + public const uint DarkReprimandChannelDamage = 373129; + public const uint DarkReprimandChannelHealing = 400171; + public const uint DarkReprimandDamage = 373130; + public const uint DarkReprimandHealing = 400187; + public const uint DazzlingLight = 196810; + public const uint DivineAegis = 47515; + public const uint DivineAegisAbsorb = 47753; + public const uint DivineBlessing = 40440; + public const uint DivineHymnHeal = 64844; + public const uint DivineImageSummon = 392990; + public const uint DivineImageEmpower = 409387; + public const uint DivineImageEmpowerStack = 405963; + public const uint DivineService = 391233; + public const uint DivineStarHoly = 110744; + public const uint DivineStarShadow = 122121; + public const uint DivineStarHolyDamage = 122128; + public const uint DivineStarHolyHeal = 110745; + public const uint DivineStarShadowDamage = 390845; + public const uint DivineStarShadowHeal = 390981; + public const uint DivineWrath = 40441; + public const uint EmpoweredRenewHeal = 391359; + public const uint Epiphany = 414553; + public const uint EpiphanyHighlight = 414556; + public const uint EssenceDevourer = 415479; + public const uint EssenceDevourerShadowfiendHeal = 415673; + public const uint EssenceDevourerMindbenderHeal = 415676; + public const uint FlashHeal = 2061; + public const uint FromDarknessComesLightAura = 390617; + public const uint GreaterHeal = 289666; + public const uint FocusedMending = 372354; + public const uint GuardianSpiritHeal = 48153; + public const uint HaloHoly = 120517; + public const uint HaloShadow = 120644; + public const uint HaloHolyDamage = 120696; + public const uint HaloHolyHeal = 120692; + public const uint HaloShadowDamage = 390964; + public const uint HaloShadowHeal = 390971; + public const uint Heal = 2060; + public const uint HealingLight = 196809; + public const uint HeavensWrath = 421558; + public const uint HolyFire = 14914; + public const uint HolyMendingHeal = 391156; + public const uint HolyNova = 132157; + public const uint HolyWordChastise = 88625; + public const uint HolyWordSalvation = 265202; + public const uint HolyWordSanctify = 34861; + public const uint HolyWordSerenity = 2050; + public const uint Holy10_1_ClassSet2PChooser = 411097; + public const uint Holy10_1_ClassSet4P = 405556; + public const uint Holy10_1_ClassSet4PEffect = 409479; + public const uint Indemnity = 373049; + public const uint ItemEfficiency = 37595; + public const uint LeapOfFaithEffect = 92832; + public const uint LevitateEffect = 111759; + public const uint LightEruption = 196812; + public const uint LightsWrathVisual = 215795; + public const uint MasochismTalent = 193063; + public const uint MasochismPeriodicHeal = 193065; + public const uint MasteryGrace = 271534; + public const uint MindDevourer = 373202; + public const uint MindDevourerAura = 373204; + public const uint MindbenderDisc = 123040; + public const uint MindbenderShadow = 200174; + public const uint Mindgames = 375901; + public const uint MindgamesVenthyr = 323673; + public const uint MindBombStun = 226943; + public const uint Misery = 238558; + public const uint OracularHeal = 26170; + public const uint PainTransformation = 372991; + public const uint PainTransformationHeal = 372994; + public const uint Penance = 47540; + public const uint PenanceChannelDamage = 47758; + public const uint PenanceChannelHealing = 47757; + public const uint PenanceDamage = 47666; + public const uint PenanceHealing = 47750; + public const uint PowerLeechMindbenderMana = 123051; + public const uint PowerLeechMindbenderInsanity = 200010; + public const uint PowerLeechShadowfiendMana = 343727; + public const uint PowerLeechShadowfiendInsanity = 262485; + public const uint PowerOfTheDarkSide = 198069; + public const uint PowerOfTheDarkSideTint = 225795; + public const uint PowerWordLife = 373481; + public const uint PowerWordRadiance = 194509; + public const uint PowerWordShield = 17; + public const uint PowerWordSolaceEnergize = 129253; + public const uint PrayerOfHealing = 596; + public const uint PrayerOfMending = 33076; + public const uint PrayerOfMendingAura = 41635; + public const uint PrayerOfMendingHeal = 33110; + public const uint PrayerOfMendingJump = 155793; + public const uint ProtectiveLightAura = 193065; + public const uint PurgeTheWicked = 204197; + public const uint PurgeTheWickedDummy = 204215; + public const uint PurgeTheWickedPeriodic = 204213; + public const uint Rapture = 47536; + public const uint Renew = 139; + public const uint RenewedHope = 197469; + public const uint RenewedHopeEffect = 197470; + public const uint RevelInPurity = 373003; + public const uint Sanctuary = 231682; + public const uint SanctuaryAbsorb = 208771; + public const uint SanctuaryAura = 208772; + public const uint ShadowCovenant = 314867; + public const uint ShadowCovenantEffect = 322105; + public const uint RhapsodyProc = 390636; + public const uint SayYourPrayers = 391186; + public const uint Schism = 424509; + public const uint SchismAura = 214621; + public const uint SearingLight = 196811; + public const uint ShadowMendDamage = 186439; + public const uint ShadowWordDeath = 32379; + public const uint ShadowWordDeathDamage = 32409; + public const uint ShadowMendPeriodicDummy = 187464; + public const uint ShadowWordPain = 589; + public const uint ShieldDiscipline = 197045; + public const uint ShieldDisciplineEffect = 47755; + public const uint SinAndPunishment = 87204; + public const uint SinsOfTheMany = 280398; + public const uint Smite = 585; + public const uint SpiritOfRedemption = 27827; + public const uint StrengthOfSoul = 197535; + public const uint StrengthOfSoulEffect = 197548; + public const uint SurgeOfLight = 109186; + public const uint SurgeOfLightEffect = 114255; + public const uint TranquilLight = 196816; + public const uint ThePenitentAura = 200347; + public const uint TrailOfLightHeal = 234946; + public const uint Trinity = 214205; + public const uint TrinityEffect = 214206; + public const uint UltimatePenitence = 421453; + public const uint UltimatePenitenceDamage = 421543; + public const uint UltimatePenitenceHeal = 421544; + public const uint UnfurlingDarkness = 341273; + public const uint UnfurlingDarknessAura = 341282; + public const uint UnfurlingDarknessDebuff = 341291; + public const uint VampiricEmbraceHeal = 15290; + public const uint VampiricTouch = 34914; + public const uint VoidShield = 199144; + public const uint VoidShieldEffect = 199145; + public const uint WeakenedSoul = 6788; + public const uint WhisperingShadows = 406777; + public const uint WhisperingShadowsDummy = 391286; - struct SpellIds + public const uint PvpRulesEnabledHardcoded = 134735; + public const uint VisualPriestPowerWordRadiance = 52872; + public const uint VisualPriestPrayerOfMending = 38945; +} + +struct CreatureIds +{ + public const uint DivineImage = 198236; + public const uint Mindbender = 62982; + public const uint Shadowfiend = 19668; +} + +class RaidCheck(Unit caster) +{ + public bool Invoke(WorldObject obj) { - public const uint AbyssalReverie = 373054; - public const uint AngelicFeatherAreatrigger = 158624; - public const uint AngelicFeatherAura = 121557; - public const uint AnsweredPrayers = 394289; - public const uint Apotheosis = 200183; - public const uint ArmorOfFaith = 28810; - public const uint Atonement = 81749; - public const uint AtonementEffect = 194384; - public const uint AtonementHeal = 81751; - public const uint Benediction = 193157; - public const uint Benevolence = 415416; - public const uint BlazeOfLight = 215768; - public const uint BlazeOfLightIncrease = 355851; - public const uint BlazeOfLightDecrease = 356084; - public const uint BlessedHealing = 70772; - public const uint BlessedLight = 196813; - public const uint BodyAndSoul = 64129; - public const uint BodyAndSoulSpeed = 65081; - public const uint CircleOfHealing = 204883; - public const uint CrystallineReflection = 373457; - public const uint CrystallineReflectionHeal = 373462; - public const uint CrystallineReflectionReflect = 373464; - public const uint DarkIndulgence = 372972; - public const uint DarkReprimand = 400169; - public const uint DarkReprimandChannelDamage = 373129; - public const uint DarkReprimandChannelHealing = 400171; - public const uint DarkReprimandDamage = 373130; - public const uint DarkReprimandHealing = 400187; - public const uint DazzlingLight = 196810; - public const uint DivineAegis = 47515; - public const uint DivineAegisAbsorb = 47753; - public const uint DivineBlessing = 40440; - public const uint DivineHymnHeal = 64844; - public const uint DivineImageSummon = 392990; - public const uint DivineImageEmpower = 409387; - public const uint DivineImageEmpowerStack = 405963; - public const uint DivineService = 391233; - public const uint DivineStarHoly = 110744; - public const uint DivineStarShadow = 122121; - public const uint DivineStarHolyDamage = 122128; - public const uint DivineStarHolyHeal = 110745; - public const uint DivineStarShadowDamage = 390845; - public const uint DivineStarShadowHeal = 390981; - public const uint DivineWrath = 40441; - public const uint EmpoweredRenewHeal = 391359; - public const uint Epiphany = 414553; - public const uint EpiphanyHighlight = 414556; - public const uint EssenceDevourer = 415479; - public const uint EssenceDevourerShadowfiendHeal = 415673; - public const uint EssenceDevourerMindbenderHeal = 415676; - public const uint FlashHeal = 2061; - public const uint FromDarknessComesLightAura = 390617; - public const uint GreaterHeal = 289666; - public const uint FocusedMending = 372354; - public const uint GuardianSpiritHeal = 48153; - public const uint HaloHoly = 120517; - public const uint HaloShadow = 120644; - public const uint HaloHolyDamage = 120696; - public const uint HaloHolyHeal = 120692; - public const uint HaloShadowDamage = 390964; - public const uint HaloShadowHeal = 390971; - public const uint Heal = 2060; - public const uint HealingLight = 196809; - public const uint HeavensWrath = 421558; - public const uint HolyFire = 14914; - public const uint HolyMendingHeal = 391156; - public const uint HolyNova = 132157; - public const uint HolyWordChastise = 88625; - public const uint HolyWordSalvation = 265202; - public const uint HolyWordSanctify = 34861; - public const uint HolyWordSerenity = 2050; - public const uint Holy101ClassSet2PChooser = 411097; - public const uint Holy101ClassSet4P = 405556; - public const uint Holy101ClassSet4PEffect = 409479; - public const uint Indemnity = 373049; - public const uint ItemEfficiency = 37595; - public const uint LeapOfFaithEffect = 92832; - public const uint LevitateEffect = 111759; - public const uint LightEruption = 196812; - public const uint LightsWrathVisual = 215795; - public const uint MasochismTalent = 193063; - public const uint MasochismPeriodicHeal = 193065; - public const uint MasteryGrace = 271534; - public const uint MindDevourer = 373202; - public const uint MindDevourerAura = 373204; - public const uint MindbenderDisc = 123040; - public const uint MindbenderShadow = 200174; - public const uint Mindgames = 375901; - public const uint MindgamesVenthyr = 323673; - public const uint MindBombStun = 226943; - public const uint Misery = 238558; - public const uint OracularHeal = 26170; - public const uint PainTransformation = 372991; - public const uint PainTransformationHeal = 372994; - public const uint Penance = 47540; - public const uint PenanceChannelDamage = 47758; - public const uint PenanceChannelHealing = 47757; - public const uint PenanceDamage = 47666; - public const uint PenanceHealing = 47750; - public const uint PowerLeechMindbenderMana = 123051; - public const uint PowerLeechMindbenderInsanity = 200010; - public const uint PowerLeechShadowfiendMana = 343727; - public const uint PowerLeechShadowfiendInsanity = 262485; - public const uint PowerOfTheDarkSide = 198069; - public const uint PowerOfTheDarkSideTint = 225795; - public const uint PowerWordLife = 373481; - public const uint PowerWordRadiance = 194509; - public const uint PowerWordShield = 17; - public const uint PowerWordSolaceEnergize = 129253; - public const uint PrayerOfHealing = 596; - public const uint PrayerOfMending = 33076; - public const uint PrayerOfMendingAura = 41635; - public const uint PrayerOfMendingHeal = 33110; - public const uint PrayerOfMendingJump = 155793; - public const uint ProtectiveLightAura = 193065; - public const uint PurgeTheWicked = 204197; - public const uint PurgeTheWickedDummy = 204215; - public const uint PurgeTheWickedPeriodic = 204213; - public const uint Rapture = 47536; - public const uint Renew = 139; - public const uint RenewedHope = 197469; - public const uint RenewedHopeEffect = 197470; - public const uint RevelInPurity = 373003; - public const uint Sanctuary = 231682; - public const uint SanctuaryAbsorb = 208771; - public const uint SanctuaryAura = 208772; - public const uint RhapsodyProc = 390636; - public const uint SayYourPrayers = 391186; - public const uint Schism = 424509; - public const uint SchismAura = 214621; - public const uint SearingLight = 196811; - public const uint ShadowMendDamage = 186439; - public const uint ShadowWordDeath = 32379; - public const uint ShadowWordDeathDamage = 32409; - public const uint ShadowMendPeriodicDummy = 187464; - public const uint ShadowWordPain = 589; - public const uint ShieldDiscipline = 197045; - public const uint ShieldDisciplineEffect = 47755; - public const uint SinAndPunishment = 87204; - public const uint SinsOfTheMany = 280398; - public const uint Smite = 585; - public const uint SpiritOfRedemption = 27827; - public const uint StrengthOfSoul = 197535; - public const uint StrengthOfSoulEffect = 197548; - public const uint SurgeOfLight = 109186; - public const uint SurgeOfLightEffect = 114255; - public const uint TranquilLight = 196816; - public const uint ThePenitentAura = 200347; - public const uint TrailOfLightHeal = 234946; - public const uint Trinity = 214205; - public const uint TrinityEffect = 214206; - public const uint UltimatePenitence = 421453; - public const uint UltimatePenitenceDamage = 421543; - public const uint UltimatePenitenceHeal = 421544; - public const uint UnfurlingDarkness = 341273; - public const uint UnfurlingDarknessAura = 341282; - public const uint UnfurlingDarknessDebuff = 341291; - public const uint VampiricEmbraceHeal = 15290; - public const uint VampiricTouch = 34914; - public const uint VoidShield = 199144; - public const uint VoidShieldEffect = 199145; - public const uint WeakenedSoul = 6788; - public const uint WhisperingShadows = 406777; - public const uint WhisperingShadowsDummy = 391286; - public const uint PvpRulesEnabledHardcoded = 134735; - public const uint VisualPriestPowerWordRadiance = 52872; - public const uint VisualPriestPrayerOfMending = 38945; + Unit target = obj.ToUnit(); + if (target != null) + return !caster.IsInRaidWith(target); + + return true; + } +} + +[Script] // 121536 - Angelic Feather talent +class spell_pri_angelic_feather_trigger : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AngelicFeatherAreatrigger); } - [Script] // 121536 - Angelic Feather talent - class spell_pri_angelic_feather_trigger : SpellScript + void HandleEffectDummy(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) + Position destPos = GetHitDest().GetPosition(); + float radius = GetEffectInfo().CalcRadius(); + + // Caster is prioritary + if (GetCaster().IsWithinDist2d(destPos, radius)) { - return ValidateSpellInfo(SpellIds.AngelicFeatherAreatrigger); + GetCaster().CastSpell(GetCaster(), SpellIds.AngelicFeatherAura, true); } - - void HandleEffectDummy(uint effIndex) + else { - Position destPos = GetHitDest().GetPosition(); - float radius = GetEffectInfo().CalcRadius(); + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.CastDifficulty = GetCastDifficulty(); + GetCaster().CastSpell(destPos, SpellIds.AngelicFeatherAreatrigger, args); + } + } - // Caster is prioritary - if (GetCaster().IsWithinDist2d(destPos, radius)) + public override void Register() + { + OnEffectHit.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // Angelic Feather areatrigger - created by SpellIds.AngelicFeatherAreatrigger +class areatrigger_pri_angelic_feather(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + // Called when the AreaTrigger has just been initialized, just before added to map + public override void OnInitialize() + { + Unit caster = at.GetCaster(); + if (caster != null) + { + List areaTriggers = caster.GetAreaTriggers(SpellIds.AngelicFeatherAreatrigger); + + if (areaTriggers.Count >= 3) + areaTriggers.First().SetDuration(0); + } + } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (caster.IsFriendlyTo(unit)) { - GetCaster().CastSpell(GetCaster(), SpellIds.AngelicFeatherAura, true); + // If target already has aura, increase duration to max 130% of initial duration + caster.CastSpell(unit, SpellIds.AngelicFeatherAura, true); + at.SetDuration(0); + } + } + } +} + +[Script] // 391387 - Answered Prayers +class spell_pri_answered_prayers : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AnsweredPrayers, SpellIds.Apotheosis) + && ValidateSpellEffect((spellInfo.Id, 1)); + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + TimeSpan extraDuration = TimeSpan.Zero; + AuraEffect durationEffect = GetEffect(1); + if (durationEffect != null) + extraDuration = TimeSpan.FromSeconds(durationEffect.GetAmount()); + + Unit target = eventInfo.GetActor(); + + Aura answeredPrayers = target.GetAura(SpellIds.AnsweredPrayers); + + // Note: if caster has no aura, we must cast it first. + if (answeredPrayers == null) + target.CastSpell(target, SpellIds.AnsweredPrayers, TriggerCastFlags.IgnoreCastInProgress); + else + { + // Note: there's no BaseValue dummy that we can use as reference, so we hardcode the increasing stack value. + answeredPrayers.ModStackAmount(1); + + // Note: if current stacks match max. stacks, trigger Apotheosis. + if (answeredPrayers.GetStackAmount() != aurEff.GetAmount()) + return; + + answeredPrayers.Remove(); + + Aura apotheosis = GetTarget().GetAura(SpellIds.Apotheosis); + if (apotheosis != null) + { + apotheosis.SetDuration(apotheosis.GetDuration() + (int)extraDuration.TotalSeconds); + apotheosis.SetMaxDuration(apotheosis.GetMaxDuration() + (int)extraDuration.TotalSeconds); } else - { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.CastDifficulty = GetCastDifficulty(); - GetCaster().CastSpell(destPos, SpellIds.AngelicFeatherAreatrigger, args); - } - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + target.CastSpell(target, SpellIds.Apotheosis, + new CastSpellExtraArgs(TriggerCastFlags.FullMask & ~TriggerCastFlags.CastDirectly) + .AddSpellMod(SpellValueMod.Duration, (int)extraDuration.TotalSeconds)); } } - [Script] // Angelic Feather areatrigger - created by SpellIds.AngelicFeatherAreatrigger - class areatrigger_pri_angelic_feather : AreaTriggerAI + public override void Register() { - public areatrigger_pri_angelic_feather(AreaTrigger areatrigger) : base(areatrigger) { } + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.AddFlatModifierBySpellLabel)); + } +} - // Called when the AreaTrigger has just been initialized, just before added to map - public override void OnInitialize() - { - Unit caster = at.GetCaster(); - if (caster != null) - { - var areaTriggers = caster.GetAreaTriggers(SpellIds.AngelicFeatherAreatrigger); - - if (areaTriggers.Count >= 3) - areaTriggers.FirstOrDefault().SetDuration(0); - } - } - - public override void OnUnitEnter(Unit unit) - { - Unit caster = at.GetCaster(); - if (caster != null) - { - if (caster.IsFriendlyTo(unit)) - { - // If target already has aura, increase duration to max 130% of initial duration - caster.CastSpell(unit, SpellIds.AngelicFeatherAura, true); - at.SetDuration(0); - } - } - } +[Script] // 26169 - Oracle Healing Bonus +class spell_pri_aq_3p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.OracularHeal); } - [Script] // 391387 - Answered Prayers - class spell_pri_answered_prayers : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + if (caster == eventInfo.GetProcTarget()) + return; + + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo == null || healInfo.GetHeal() == 0) + return; + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, MathFunctions.CalculatePct((int)(healInfo.GetHeal()), 10)); + caster.CastSpell(caster, SpellIds.OracularHeal, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 81749 - Atonement +class spell_pri_atonement : AuraScript +{ + List _appliedAtonements; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AtonementHeal, SpellIds.SinsOfTheMany) + && ValidateSpellEffect((spellInfo.Id, 1), (SpellIds.SinsOfTheMany, 2)); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo() != null; + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + TriggerAtonementHealOnTargets(aurEff, eventInfo); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); + } + + public void AddAtonementTarget(ObjectGuid target) + { + _appliedAtonements.Add(target); + + UpdateSinsOfTheManyValue(); + } + + public void RemoveAtonementTarget(ObjectGuid target) + { + _appliedAtonements.Remove(target); + + UpdateSinsOfTheManyValue(); + } + + public List GetAtonementTargets() + { + return _appliedAtonements; + } + + public class TriggerArgs + { + public SpellInfo TriggeredBy; + public SpellSchoolMask DamageSchoolMask; + } + + public void TriggerAtonementHealOnTargets(AuraEffect atonementEffect, ProcEventInfo eventInfo) + { + Unit priest = GetUnitOwner(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + CastSpellExtraArgs args = new(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + + // Note: atonementEffect holds the correct amount since we passed the effect in the AuraScript that calls this method. + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), atonementEffect.GetAmount())); + + args.SetCustomArg(new TriggerArgs() { - return ValidateSpellInfo(SpellIds.AnsweredPrayers, SpellIds.Apotheosis) - && ValidateSpellEffect((spellInfo.Id, 1)); - } + TriggeredBy = eventInfo.GetSpellInfo(), + DamageSchoolMask = eventInfo.GetDamageInfo().GetSchoolMask() + }); - void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + float distanceLimit = GetEffectInfo(1).CalcValue(); + + _appliedAtonements.RemoveAll(targetGuid => { - TimeSpan extraDuration = TimeSpan.FromMilliseconds(0); - AuraEffect durationEffect = GetEffect(1); - if (durationEffect != null) - extraDuration = TimeSpan.FromSeconds(durationEffect.GetAmount()); - - Unit target = eventInfo.GetActor(); - - Aura answeredPrayers = target.GetAura(SpellIds.AnsweredPrayers); - - // Note: if caster has no aura, we must cast it first. - if (answeredPrayers == null) - target.CastSpell(target, SpellIds.AnsweredPrayers, TriggerCastFlags.IgnoreCastInProgress); - else + Unit target = Global.ObjAccessor.GetUnit(priest, targetGuid); + if (target != null) { - // Note: there's no BaseValue dummy that we can use as reference, so we hardcode the increasing stack value. - answeredPrayers.ModStackAmount(1); + if (target.IsInDist2d(priest, distanceLimit)) + priest.CastSpell(target, SpellIds.AtonementHeal, args); - // Note: if current stacks match max. stacks, trigger Apotheosis. - if (answeredPrayers.GetStackAmount() != aurEff.GetAmount()) - return; - - answeredPrayers.Remove(); - - Aura apotheosis = GetTarget().GetAura(SpellIds.Apotheosis); - if (apotheosis != null) - { - apotheosis.SetDuration((int)(apotheosis.GetDuration() + extraDuration.TotalMilliseconds)); - apotheosis.SetMaxDuration((int)(apotheosis.GetMaxDuration() + extraDuration.TotalMilliseconds)); - } - else - target.CastSpell(target, SpellIds.Apotheosis, - new CastSpellExtraArgs(TriggerCastFlags.FullMask & ~TriggerCastFlags.CastDirectly) - .AddSpellMod(SpellValueMod.Duration, (int)extraDuration.TotalMilliseconds)); - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleOnProc, 0, AuraType.AddFlatModifierBySpellLabel)); - } - } - - [Script] // 26169 - Oracle Healing Bonus - class spell_pri_aq_3p_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.OracularHeal); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - if (caster == eventInfo.GetProcTarget()) - return; - - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo == null || healInfo.GetHeal() == 0) - return; - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, MathFunctions.CalculatePct((int)(healInfo.GetHeal()), 10)); - caster.CastSpell(caster, SpellIds.OracularHeal, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 81749 - Atonement - class spell_pri_atonement : AuraScript - { - List _appliedAtonements = new(); - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AtonementHeal, SpellIds.SinsOfTheMany) - && ValidateSpellEffect((spellInfo.Id, 1), (SpellIds.SinsOfTheMany, 2)); - } - - static bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetDamageInfo() != null; - } - - void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - TriggerAtonementHealOnTargets(aurEff, eventInfo); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); - } - - public void AddAtonementTarget(ObjectGuid target) - { - _appliedAtonements.Add(target); - - UpdateSinsOfTheManyValue(); - } - - public void RemoveAtonementTarget(ObjectGuid target) - { - _appliedAtonements.Remove(target); - - UpdateSinsOfTheManyValue(); - } - - public List GetAtonementTargets() - { - return _appliedAtonements; - } - - public class TriggerArgs - { - public SpellInfo TriggeredBy; - public SpellSchoolMask DamageSchoolMask; - } - - public void TriggerAtonementHealOnTargets(AuraEffect atonementEffect, ProcEventInfo eventInfo) - { - Unit priest = GetUnitOwner(); - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - CastSpellExtraArgs args = new(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); - - // Note: atonementEffect holds the correct amount Since we passed the effect in the AuraScript that calls this method. - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), atonementEffect.GetAmount())); - - args.SetCustomArg(new TriggerArgs() { TriggeredBy = eventInfo.GetSpellInfo(), DamageSchoolMask = eventInfo.GetDamageInfo().GetSchoolMask() }); - - float distanceLimit = GetEffectInfo(1).CalcValue(); - - _appliedAtonements.RemoveAll(targetGuid => - { - Unit target = ObjAccessor.GetUnit(priest, targetGuid); - if (target != null) - { - if (target.IsInDist2d(priest, distanceLimit)) - priest.CastSpell(target, SpellIds.AtonementHeal, args); - - return false; - } - - return true; - }); - } - - void UpdateSinsOfTheManyValue() - { - // Note: the damage dimish starts at the 6th application as of 10.0.5. - float[] damageByStack = { 20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 17.5f, 15.0f, 12.5f, 10.0f, 7.5f, 5.5f, 4.0f, 2.5f, 2.0f, 1.5f, 1.25f, 1.0f, 0.75f, 0.63f, 0.5f }; - - foreach (uint effectIndex in new[] { 0, 1, 2 }) - { - AuraEffect sinOfTheMany = GetUnitOwner().GetAuraEffect(SpellIds.SinsOfTheMany, effectIndex); - if (sinOfTheMany != null) - sinOfTheMany.ChangeAmount((int)damageByStack[Math.Min(_appliedAtonements.Count, damageByStack.Length - 1)]); - } - } - } - - [Script] // 81751 - Atonement (Heal) - class spell_pri_abyssal_reverie : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.AbyssalReverie, 0)); - } - - void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) - { - spell_pri_atonement.TriggerArgs args = (spell_pri_atonement.TriggerArgs)GetSpell().m_customArg; - if (args == null || (args.DamageSchoolMask & SpellSchoolMask.Shadow) == 0) - return; - - AuraEffect abyssalReverieEffect = GetCaster().GetAuraEffect(SpellIds.AbyssalReverie, 0); - if (abyssalReverieEffect != null) - MathFunctions.AddPct(ref pctMod, abyssalReverieEffect.GetAmount()); - } - - public override void Register() - { - CalcHealing.Add(new(CalculateHealingBonus)); - } - } - - // 17 - Power Word: Shield - // 139 - Renew - // 2061 - Flash Heal - [Script] // 194509 - Power Word: Radiance - class spell_pri_atonement_effect : SpellScript - { - uint _effectSpellId = SpellIds.AtonementEffect; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Atonement, SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.TrinityEffect, SpellIds.PowerWordRadiance, SpellIds.PowerWordShield) - && ValidateSpellEffect((SpellIds.PowerWordRadiance, 3), (SpellIds.Indemnity, 0)); - } - - public override bool Load() - { - Unit caster = GetCaster(); - if (!caster.HasAura(SpellIds.Atonement)) return false; - - // only apply Trinity if the Priest has both Trinity and Atonement and the triggering spell is Power Word: Shield. - if (caster.HasAura(SpellIds.Trinity)) - { - if (GetSpellInfo().Id != SpellIds.PowerWordShield) - return false; - - _effectSpellId = SpellIds.TrinityEffect; } return true; - } - - void HandleOnHitTarget() - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.SetTriggeringSpell(GetSpell()); - - switch (GetSpellInfo().Id) - { - case SpellIds.PowerWordShield: - AuraEffect indemnity = caster.GetAuraEffect(SpellIds.Indemnity, 0); - if (indemnity != null) - args.AddSpellMod(SpellValueMod.Duration, (int)(TimeSpan.FromSeconds(indemnity.GetAmount()) + TimeSpan.FromMilliseconds(Aura.CalcMaxDuration(Global.SpellMgr.GetSpellInfo(_effectSpellId, GetCastDifficulty()), caster, GetSpell().GetPowerCost()))).TotalSeconds); - break; - case SpellIds.PowerWordRadiance: - // Power Word: Radiance applies Atonement at 60 % (without modifiers) of its total duration. - args.AddSpellMod(SpellValueModFloat.DurationPct, GetEffectInfo(3).CalcValue(caster)); - break; - default: - break; - } - - caster.CastSpell(target, _effectSpellId, args); - } - - public override void Register() - { - AfterHit.Add(new(HandleOnHitTarget)); - } + }); } - [Script] // 194384 - Atonement (Buff), 214206 - Atonement [Trinity] (Buff) - class spell_pri_atonement_effect_AuraScript : AuraScript + void UpdateSinsOfTheManyValue() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Atonement); - } + // Note: the damage dimish starts at the 6th application as of 10.0.5. + float[] damageByStack = [20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 17.5f, 15.0f, 12.5f, 10.0f, 7.5f, 5.5f, 4.0f, 2.5f, 2.0f, 1.5f, 1.25f, 1.0f, 0.75f, 0.63f, 0.5f]; - void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + foreach (uint effectIndex in new uint[] { 0, 1, 2 }) { - Unit caster = GetCaster(); - if (caster != null) - { - Aura atonement = caster.GetAura(SpellIds.Atonement); - if (atonement != null) - { - spell_pri_atonement script = atonement.GetScript(); - if (script != null) - script.AddAtonementTarget(GetTarget().GetGUID()); - } - } - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - { - Aura atonement = caster.GetAura(SpellIds.Atonement); - if (atonement != null) - { - spell_pri_atonement script = atonement.GetScript(); - if (script != null) - script.RemoveAtonementTarget(GetTarget().GetGUID()); - } - } - } - - public override void Register() - { - OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AuraEffect sinOfTheMany = GetUnitOwner().GetAuraEffect(SpellIds.SinsOfTheMany, effectIndex); + if (sinOfTheMany != null) + sinOfTheMany.ChangeAmount((int)damageByStack[Math.Min(_appliedAtonements.Count, (byte)(damageByStack.Length - 1))]); } } +} - [Script] // 195178 - Atonement (Passive) - class spell_pri_atonement_passive : AuraScript +[Script] // 81751 - Atonement (Heal) +class spell_pri_abyssal_reverie : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) + return ValidateSpellEffect((SpellIds.AbyssalReverie, 0)); + } + + void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) + { + spell_pri_atonement.TriggerArgs args = (spell_pri_atonement.TriggerArgs)GetSpell().m_customArg; + if (args == null || (args.DamageSchoolMask & SpellSchoolMask.Shadow) == 0) + return; + + AuraEffect abyssalReverieEffect = GetCaster().GetAuraEffect(SpellIds.AbyssalReverie, 0); + if (abyssalReverieEffect != null) + MathFunctions.AddPct(ref pctMod, abyssalReverieEffect.GetAmount()); + } + + public override void Register() + { + CalcHealing.Add(new(CalculateHealingBonus)); + } +} + +// 17 - Power Word: Shield +// 139 - Renew +// 2061 - Flash Heal +[Script] // 194509 - Power Word: Radiance +class spell_pri_atonement_effect : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Atonement, SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.TrinityEffect, SpellIds.PowerWordRadiance, SpellIds.PowerWordShield) + && ValidateSpellEffect((SpellIds.PowerWordRadiance, 3), (SpellIds.Indemnity, 0)); + } + + public override bool Load() + { + Unit caster = GetCaster(); + if (!caster.HasAura(SpellIds.Atonement)) + return false; + + // only apply Trinity if the Priest has both Trinity and Atonement and the triggering spell is Power Word: Shield. + if (caster.HasAura(SpellIds.Trinity)) { - return ValidateSpellEffect((SpellIds.Atonement, 0)); + if (GetSpellInfo().Id != SpellIds.PowerWordShield) + return false; + + _effectSpellId = SpellIds.TrinityEffect; } - void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit target = GetTarget(); - Unit summoner = target.GetOwner(); - if (summoner == null) - return; + return true; + } - AuraEffect atonementEffect = summoner.GetAuraEffect(SpellIds.Atonement, 0); - if (atonementEffect != null) + void HandleOnHitTarget() + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.SetTriggeringSpell(GetSpell()); + + switch (GetSpellInfo().Id) + { + case SpellIds.PowerWordShield: + AuraEffect indemnity = caster.GetAuraEffect(SpellIds.Indemnity, 0); + if (indemnity != null) + args.AddSpellMod(SpellValueMod.Duration, + (int)(TimeSpan.FromSeconds(indemnity.GetAmount()) + + TimeSpan.FromSeconds(Aura.CalcMaxDuration(Global.SpellMgr.GetSpellInfo(_effectSpellId, GetCastDifficulty()), + caster, GetSpell().GetPowerCost()))).TotalSeconds); + break; + case SpellIds.PowerWordRadiance: + // Power Word: Radiance applies Atonement at 60 % (without modifiers) of its total duration. + args.AddSpellMod(SpellValueModFloat.DurationPct, GetEffectInfo(3).CalcValue(caster)); + break; + default: + break; + } + + caster.CastSpell(target, _effectSpellId, args); + } + + public override void Register() + { + AfterHit.Add(new(HandleOnHitTarget)); + } + + uint _effectSpellId = SpellIds.AtonementEffect; +} + +[Script] // 194384 - Atonement (Buff), 214206 - Atonement [Trinity] (Buff) +class spell_pri_atonement_effect_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Atonement); + } + + void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + { + Aura atonement = caster.GetAura(SpellIds.Atonement); + if (atonement != null) { - spell_pri_atonement script = atonementEffect.GetBase().GetScript(); + spell_pri_atonement script = atonement.GetScript(); if (script != null) - script.TriggerAtonementHealOnTargets(atonementEffect, eventInfo); + script.AddAtonementTarget(GetTarget().GetGUID()); } } - - public override void Register() - { - OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); - } } - [Script] // 33110 - Prayer of Mending (Heal) - class spell_pri_benediction : SpellScript + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) + Unit caster = GetCaster(); + if (caster != null) { - return ValidateSpellInfo(SpellIds.Renew) + Aura atonement = caster.GetAura(SpellIds.Atonement); + if (atonement != null) + { + spell_pri_atonement script = atonement.GetScript(); + if (script != null) + script.RemoveAtonementTarget(GetTarget().GetGUID()); + } + } + } + + public override void Register() + { + OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 195178 - Atonement (Passive) +class spell_pri_atonement_passive : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.Atonement, 0)); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo() != null; + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + Unit summoner = target.GetOwner(); + if (summoner == null) + return; + + AuraEffect atonementEffect = summoner.GetAuraEffect(SpellIds.Atonement, 0); + if (atonementEffect != null) + { + spell_pri_atonement script = atonementEffect.GetBase().GetScript(); + if (script != null) + script.TriggerAtonementHealOnTargets(atonementEffect, eventInfo); + } + } + + public override void Register() + { + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); + } +} + +[Script] // 33110 - Prayer of Mending (Heal) +class spell_pri_benediction : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Renew) && ValidateSpellEffect((SpellIds.Benediction, 0)); - } - - void HandleEffectHitTarget(uint effIndex) - { - AuraEffect benediction = GetCaster().GetAuraEffect(SpellIds.Benediction, 0); - if (benediction != null) - if (RandomHelper.randChance(benediction.GetAmount())) - GetCaster().CastSpell(GetHitUnit(), SpellIds.Renew, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Heal)); - } } - [Script] // 215768 - Blaze of Light - class spell_pri_blaze_of_light : AuraScript + void HandleEffectHitTarget(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlazeOfLightDecrease, SpellIds.BlazeOfLightIncrease); - } - - void HandleProc(ProcEventInfo eventInfo) - { - Unit procTarget = eventInfo.GetProcTarget(); - if (procTarget == null) - return; - - if (GetTarget().IsValidAttackTarget(procTarget)) - GetTarget().CastSpell(procTarget, SpellIds.BlazeOfLightDecrease, TriggerCastFlags.CastDirectly | TriggerCastFlags.IgnoreCastInProgress); - else - GetTarget().CastSpell(procTarget, SpellIds.BlazeOfLightIncrease, TriggerCastFlags.CastDirectly | TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnProc.Add(new(HandleProc)); - } + AuraEffect benediction = GetCaster().GetAuraEffect(SpellIds.Benediction, 0); + if (benediction != null) + if (RandomHelper.randChance(benediction.GetAmount())) + GetCaster().CastSpell(GetHitUnit(), SpellIds.Renew, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); } - [Script] // 204883 - Circle of Healing - class spell_pri_circle_of_healing : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Heal)); + } +} - void FilterTargets(List targets) - { - // Note: we must Remove one Math.Since target is always chosen. - uint maxTargets = (uint)GetSpellInfo().GetEffect(1).CalcValue(GetCaster()) - 1; - - SelectRandomInjuredTargets(targets, maxTargets, true); - - Unit explicitTarget = GetExplTargetUnit(); - if (explicitTarget != null) - targets.Add(explicitTarget); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - } +[Script] // 215768 - Blaze of Light +class spell_pri_blaze_of_light : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlazeOfLightDecrease, SpellIds.BlazeOfLightIncrease); } - [Script] // 17 - Power Word: Shield - class spell_pri_crystalline_reflection : AuraScript + void HandleProc(ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CrystallineReflection, SpellIds.CrystallineReflectionHeal, SpellIds.CrystallineReflectionReflect) - && ValidateSpellEffect((SpellIds.CrystallineReflection, 0)); - } + Unit procTarget = eventInfo.GetProcTarget(); + if (procTarget == null) + return; - void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - // Crystalline Reflection Heal - if (caster.HasAura(SpellIds.CrystallineReflection)) - caster.CastSpell(GetTarget(), SpellIds.CrystallineReflectionHeal, new CastSpellExtraArgs(aurEff) - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); - } - - void HandleAfterAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - AuraEffect auraEff = caster.GetAuraEffect(SpellIds.CrystallineReflection, 0); - if (auraEff == null) - return; - - Unit attacker = dmgInfo.GetAttacker(); - if (attacker == null) - return; - - CastSpellExtraArgs args = new(TriggerCastFlags.DontReportCastError); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(absorbAmount, auraEff.GetAmount())); - caster.CastSpell(attacker, SpellIds.CrystallineReflectionReflect, args); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleOnApply, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.RealOrReapplyMask)); - AfterEffectAbsorb.Add(new(HandleAfterAbsorb, 0)); - } + if (GetTarget().IsValidAttackTarget(procTarget)) + GetTarget().CastSpell(procTarget, SpellIds.BlazeOfLightDecrease, (TriggerCastFlags.CastDirectly | TriggerCastFlags.IgnoreCastInProgress)); + else + GetTarget().CastSpell(procTarget, SpellIds.BlazeOfLightIncrease, (TriggerCastFlags.CastDirectly | TriggerCastFlags.IgnoreCastInProgress)); } - [Script] // 8092 - Mind Blast - class spell_pri_dark_indulgence : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.DarkIndulgence, 0)); - } + OnProc.Add(new(HandleProc)); + } +} - void HandleEffectHit(uint effIndex) - { - AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.DarkIndulgence, 0); - if (aurEff == null) - return; - - if (RandomHelper.randChance(aurEff.GetAmount())) - GetCaster().CastSpell(GetCaster(), SpellIds.PowerOfTheDarkSide, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffectHit, 0, SpellEffectName.SchoolDamage)); - } +[Script] // 204883 - Circle of Healing +class spell_pri_circle_of_healing : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); } - struct DivineImageHelpers + void FilterTargets(List targets) { - const uint NpcPriestDivineImage = 198236; + // Note: we must remove one since target is always chosen. + uint maxTargets = (uint)(GetSpellInfo().GetEffect(1).CalcValue(GetCaster()) - 1); - public static Unit GetSummon(Unit owner) - { - foreach (Unit summon in owner.m_Controlled) - if (summon.GetEntry() == NpcPriestDivineImage) - return summon; + SelectRandomInjuredTargets(targets, maxTargets, true); - return null; - } - - public static uint? GetSpellToCast(uint spellId) - { - switch (spellId) - { - case SpellIds.Renew: - return SpellIds.TranquilLight; - case SpellIds.PowerWordShield: - case SpellIds.PowerWordLife: - case SpellIds.FlashHeal: - case SpellIds.Heal: - case SpellIds.GreaterHeal: - case SpellIds.HolyWordSerenity: - return SpellIds.HealingLight; - case SpellIds.PrayerOfMending: - case SpellIds.PrayerOfMendingHeal: - return SpellIds.BlessedLight; - case SpellIds.PrayerOfHealing: - case SpellIds.CircleOfHealing: - case SpellIds.HaloHoly: - case SpellIds.DivineStarHolyHeal: - case SpellIds.DivineHymnHeal: - case SpellIds.HolyWordSanctify: - case SpellIds.HolyWordSalvation: - return SpellIds.DazzlingLight; - case SpellIds.ShadowWordPain: - case SpellIds.Smite: - case SpellIds.HolyFire: - case SpellIds.ShadowWordDeath: - case SpellIds.HolyWordChastise: - case SpellIds.Mindgames: - case SpellIds.MindgamesVenthyr: - return SpellIds.SearingLight; - case SpellIds.HolyNova: - return SpellIds.LightEruption; - default: - break; - } - - return null; - } - - public static void Trigger(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit target = eventInfo.GetActor(); - if (target == null) - return; - - Unit divineImage = GetSummon(target); - if (divineImage == null) - return; - - var spellId = GetSpellToCast(eventInfo.GetSpellInfo().Id); - if (!spellId.HasValue) - return; - - divineImage.CastSpell(eventInfo.GetProcSpell().m_targets, spellId.Value, aurEff); - } + Unit explicitTarget = GetExplTargetUnit(); + if (explicitTarget != null) + targets.Insert(0, explicitTarget); } - [Script] // 392988 - Divine Image - class spell_pri_divine_image : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +[Script] // 17 - Power Word: Shield +class spell_pri_crystalline_reflection : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CrystallineReflection, SpellIds.CrystallineReflectionHeal, SpellIds.CrystallineReflectionReflect) && ValidateSpellEffect((SpellIds.CrystallineReflection, 0)); + } + + void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + // Crystalline Reflection Heal + if (caster.HasAura(SpellIds.CrystallineReflection)) + caster.CastSpell(GetTarget(), SpellIds.CrystallineReflectionHeal, new CastSpellExtraArgs(aurEff) + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); + } + + void HandleAfterAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + AuraEffect auraEff = caster.GetAuraEffect(SpellIds.CrystallineReflection, 0); + if (auraEff == null) + return; + + Unit attacker = dmgInfo.GetAttacker(); + if (attacker == null) + return; + + CastSpellExtraArgs args = new(TriggerCastFlags.DontReportCastError); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(absorbAmount, auraEff.GetAmount())); + caster.CastSpell(attacker, SpellIds.CrystallineReflectionReflect, args); + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleOnApply, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.RealOrReapplyMask)); + AfterEffectAbsorb.Add(new(HandleAfterAbsorb, 0)); + } +} + +[Script] // 8092 - Mind Blast +class spell_pri_dark_indulgence : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DarkIndulgence, 0)); + } + + void HandleEffectHit(uint effIndex) + { + AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.DarkIndulgence, 0); + if (aurEff == null) + return; + + if (RandomHelper.randChance(aurEff.GetAmount())) + GetCaster().CastSpell(GetCaster(), SpellIds.PowerOfTheDarkSide, true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEffectHit, 0, SpellEffectName.SchoolDamage)); + } +} + +struct DivineImageHelpers +{ + public static Unit GetSummon(Unit owner) + { + foreach (Unit summon in owner.m_Controlled) + if (summon.GetEntry() == CreatureIds.DivineImage) + return summon; + + return null; + } + + public static uint? GetSpellToCast(uint spellId) + { + switch (spellId) { - return ValidateSpellInfo(SpellIds.DivineImageSummon, SpellIds.DivineImageEmpower, SpellIds.DivineImageEmpowerStack); + case SpellIds.Renew: + return SpellIds.TranquilLight; + case SpellIds.PowerWordShield: + case SpellIds.PowerWordLife: + case SpellIds.FlashHeal: + case SpellIds.Heal: + case SpellIds.GreaterHeal: + case SpellIds.HolyWordSerenity: + return SpellIds.HealingLight; + case SpellIds.PrayerOfMending: + case SpellIds.PrayerOfMendingHeal: + return SpellIds.BlessedLight; + case SpellIds.PrayerOfHealing: + case SpellIds.CircleOfHealing: + case SpellIds.HaloHoly: + case SpellIds.DivineStarHolyHeal: + case SpellIds.DivineHymnHeal: + case SpellIds.HolyWordSanctify: + case SpellIds.HolyWordSalvation: + return SpellIds.DazzlingLight; + case SpellIds.ShadowWordPain: + case SpellIds.Smite: + case SpellIds.HolyFire: + case SpellIds.ShadowWordDeath: + case SpellIds.HolyWordChastise: + case SpellIds.Mindgames: + case SpellIds.MindgamesVenthyr: + return SpellIds.SearingLight; + case SpellIds.HolyNova: + return SpellIds.LightEruption; + default: + break; } - static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + return null; + } + + public static void Trigger(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = eventInfo.GetActor(); + if (target == null) + return; + + Unit divineImage = GetSummon(target); + if (divineImage == null) + return; + + uint? spellId = GetSpellToCast(eventInfo.GetSpellInfo().Id); + if (!spellId.HasValue) + return; + + divineImage.CastSpell(new CastSpellTargetArg(eventInfo.GetProcSpell().m_targets), spellId.Value, aurEff); + } +} + +[Script] // 392988 - Divine Image +class spell_pri_divine_image : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DivineImageSummon, SpellIds.DivineImageEmpower, SpellIds.DivineImageEmpowerStack); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = eventInfo.GetActor(); + if (target == null) + return; + + // Note: if target has an active Divine Image, we should empower it rather than summoning a new one. + Unit divineImage = DivineImageHelpers.GetSummon(target); + if (divineImage != null) { - Unit target = eventInfo.GetActor(); - if (target == null) - return; + // Note: Divine Image now teleports near the target when they cast a Holy Word spell if the Divine Image is further than 15 yards away (Patch 10.1.0). + if (target.GetDistance(divineImage) > 15.0f) + divineImage.NearTeleportTo(target.GetRandomNearPosition(3.0f)); - // Note: if target has an active Divine Image, we should empower it rather than summoning a new one. - Unit divineImage = DivineImageHelpers.GetSummon(target); - if (divineImage != null) - { - // Note: Divine Image now teleports near the target when they cast a Holy Word spell if the Divine Image is further than 15 yards away (Patch 10.1.0). - if (target.GetDistance(divineImage) > 15.0f) - divineImage.NearTeleportTo(target.GetRandomNearPosition(3.0f)); + TempSummon tempSummon = divineImage.ToTempSummon(); + if (tempSummon != null) + tempSummon.RefreshTimer(); - TempSummon tempSummon = divineImage.ToTempSummon(); - if (tempSummon != null) - tempSummon.RefreshTimer(); - - divineImage.CastSpell(divineImage, SpellIds.DivineImageEmpower, eventInfo.GetProcSpell()); - } - else - { - target.CastSpell(target, SpellIds.DivineImageSummon, new CastSpellExtraArgs() - .SetTriggeringAura(aurEff) - .SetTriggeringSpell(eventInfo.GetProcSpell()) - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DisallowProcEvents | TriggerCastFlags.DontReportCastError)); - - // Note: Divine Image triggers a cast immediately based on the Holy Word cast. - DivineImageHelpers.Trigger(aurEff, eventInfo); - } - - target.CastSpell(target, SpellIds.DivineImageEmpowerStack, new CastSpellExtraArgs() + divineImage.CastSpell(divineImage, SpellIds.DivineImageEmpower, eventInfo.GetProcSpell()); + } + else + { + target.CastSpell(target, SpellIds.DivineImageSummon, new CastSpellExtraArgs() .SetTriggeringAura(aurEff) .SetTriggeringSpell(eventInfo.GetProcSpell()) .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DisallowProcEvents | TriggerCastFlags.DontReportCastError)); + + // Note: Divine Image triggers a cast immediately based on the Holy Word cast. + DivineImageHelpers.Trigger(aurEff, eventInfo); } - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + target.CastSpell(target, SpellIds.DivineImageEmpowerStack, new CastSpellExtraArgs() + .SetTriggeringAura(aurEff) + .SetTriggeringSpell(eventInfo.GetProcSpell()) + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DisallowProcEvents | TriggerCastFlags.DontReportCastError)); } - [Script] // 405216 - Divine Image (Spell Cast Check) - class spell_pri_divine_image_spell_triggered : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Renew, SpellIds.PowerWordShield, SpellIds.PowerWordLife, SpellIds.FlashHeal, SpellIds.HolyWordSerenity, SpellIds.PrayerOfMending, - SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfHealing, SpellIds.CircleOfHealing, SpellIds.HaloHoly, SpellIds.DivineStarHolyHeal, SpellIds.DivineHymnHeal, SpellIds.HolyWordSanctify, - SpellIds.HolyWordSalvation, SpellIds.Smite, SpellIds.HolyFire, SpellIds.ShadowWordDeath, SpellIds.ShadowWordPain, SpellIds.Mindgames, SpellIds.MindgamesVenthyr, SpellIds.HolyWordChastise, - SpellIds.HolyNova, SpellIds.TranquilLight, SpellIds.HealingLight, SpellIds.BlessedLight, SpellIds.DazzlingLight, SpellIds.SearingLight, SpellIds.LightEruption, SpellIds.DivineImageEmpowerStack); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - static bool CheckProc(ProcEventInfo eventInfo) - { - return DivineImageHelpers.GetSummon(eventInfo.GetActor()) != null; - } - - void HandleAfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.DivineImageEmpowerStack); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(DivineImageHelpers.Trigger, 0, AuraType.Dummy)); - AfterEffectRemove.Add(new(HandleAfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } +[Script] // 405216 - Divine Image (Spell Cast Check) +class spell_pri_divine_image_spell_triggered : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo + ( + SpellIds.Renew, + SpellIds.PowerWordShield, + SpellIds.PowerWordLife, + SpellIds.FlashHeal, + SpellIds.HolyWordSerenity, + SpellIds.PrayerOfMending, + SpellIds.PrayerOfMendingHeal, + SpellIds.PrayerOfHealing, + SpellIds.CircleOfHealing, + SpellIds.HaloHoly, + SpellIds.DivineStarHolyHeal, + SpellIds.DivineHymnHeal, + SpellIds.HolyWordSanctify, + SpellIds.HolyWordSalvation, + SpellIds.Smite, + SpellIds.HolyFire, + SpellIds.ShadowWordDeath, + SpellIds.ShadowWordPain, + SpellIds.Mindgames, + SpellIds.MindgamesVenthyr, + SpellIds.HolyWordChastise, + SpellIds.HolyNova, + SpellIds.TranquilLight, + SpellIds.HealingLight, + SpellIds.BlessedLight, + SpellIds.DazzlingLight, + SpellIds.SearingLight, + SpellIds.LightEruption, + SpellIds.DivineImageEmpowerStack + ); } - // 405963 Divine Image - [Script] // 409387 Divine Image - class spell_pri_divine_image_stack_timer : AuraScript + static bool CheckProc(ProcEventInfo eventInfo) { - void TrackStackApplicationTime(AuraEffect aurEff, AuraEffectHandleModes mode) - { - var spellId = GetId(); - var owner = GetUnitOwner(); - GetUnitOwner().m_Events.AddEventAtOffset(() => owner.RemoveAuraFromStack(spellId), TimeSpan.FromMilliseconds(GetMaxDuration())); - } - - public override void Register() - { - AfterEffectApply.Add(new(TrackStackApplicationTime, 0, AuraType.Any, AuraEffectHandleModes.RealOrReapplyMask)); - } + return DivineImageHelpers.GetSummon(eventInfo.GetActor()) != null; } - [Script] // 33110 - Prayer of Mending (Heal) - class spell_pri_divine_service : SpellScript + void HandleAfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PrayerOfMendingAura) + GetTarget().RemoveAurasDueToSpell(SpellIds.DivineImageEmpowerStack); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(DivineImageHelpers.Trigger, 0, AuraType.Dummy)); + AfterEffectRemove.Add(new(HandleAfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +// 405963 Divine Image +[Script] // 409387 Divine Image +class spell_pri_divine_image_stack_timer : AuraScript +{ + void TrackStackApplicationTime(AuraEffect aurEff, AuraEffectHandleModes mode) + { + var spelId = GetId(); + var owner = GetUnitOwner(); + + GetUnitOwner().m_Events.AddEventAtOffset(() => owner.RemoveAuraFromStack(spelId), TimeSpan.FromSeconds(GetMaxDuration())); + } + + public override void Register() + { + AfterEffectApply.Add(new(TrackStackApplicationTime, 0, AuraType.Any, AuraEffectHandleModes.RealOrReapplyMask)); + } +} + +[Script] // 33110 - Prayer of Mending (Heal) +class spell_pri_divine_service : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMendingAura) && ValidateSpellEffect((SpellIds.DivineService, 0)); - } + } - void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) + void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) + { + AuraEffect divineServiceEffect = GetCaster().GetAuraEffect(SpellIds.DivineService, 0); + if (divineServiceEffect != null) { - AuraEffect divineServiceEffect = GetCaster().GetAuraEffect(SpellIds.DivineService, 0); - if (divineServiceEffect != null) - { - Aura prayerOfMending = victim.GetAura(SpellIds.PrayerOfMendingAura, GetCaster().GetGUID()); - if (prayerOfMending != null) - MathFunctions.AddPct(ref pctMod, (int)(divineServiceEffect.GetAmount() * prayerOfMending.GetStackAmount())); - } - } - - public override void Register() - { - CalcHealing.Add(new(CalculateHealingBonus)); + Aura prayerOfMending = victim.GetAura(SpellIds.PrayerOfMendingAura, GetCaster().GetGUID()); + if (prayerOfMending != null) + MathFunctions.AddPct(ref pctMod, (int)divineServiceEffect.GetAmount() * prayerOfMending.GetStackAmount()); } } - [Script] // 122121 - Divine Star (Shadow) - class spell_pri_divine_star_shadow : SpellScript + public override void Register() { - void HandleHitTarget(uint effIndex) - { - Unit caster = GetCaster(); + CalcHealing.Add(new(CalculateHealingBonus)); + } +} - if (caster.GetPowerType() != (PowerType)GetEffectInfo().MiscValue) - PreventHitDefaultEffect(effIndex); - } +[Script] // 122121 - Divine Star (Shadow) +class spell_pri_divine_star_shadow : SpellScript +{ + void HandleHitTarget(uint effIndex) + { + Unit caster = GetCaster(); - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHitTarget, 2, SpellEffectName.Energize)); - } + if ((int)caster.GetPowerType() != GetEffectInfo().MiscValue) + PreventHitDefaultEffect(effIndex); } - // 110744 - Divine Star (Holy) - [Script] // 122121 - Divine Star (Shadow) - class areatrigger_pri_divine_star : AreaTriggerAI + public override void Register() { - TaskScheduler _scheduler = new(); - Position _casterCurrentPosition; - List _affectedUnits = new(); + OnEffectHitTarget.Add(new(HandleHitTarget, 2, SpellEffectName.Energize)); + } +} - public areatrigger_pri_divine_star(AreaTrigger areatrigger) : base(areatrigger) { } +// 110744 - Divine Star (Holy) +[Script] // 122121 - Divine Star (Shadow) +class areatrigger_pri_divine_star(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TaskScheduler _scheduler = new(); + Position _casterCurrentPosition; + List _affectedUnits = new(); - public override void OnInitialize() + public override void OnInitialize() + { + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(at.GetSpellId(), Difficulty.None); + if (spellInfo == null) + return; + + if (spellInfo.GetEffects().Count <= 1) + return; + + Unit caster = at.GetCaster(); + if (caster == null) + return; + + _casterCurrentPosition = caster.GetPosition(); + + // Note: max. distance at which the Divine Star can travel to is 1's BasePoints yards. + float maxTravelDistance = (float)spellInfo.GetEffect(1).CalcValue(caster); + + Position destPos = _casterCurrentPosition; + at.MovePositionToFirstCollision(destPos, maxTravelDistance, 0.0f); + + PathGenerator firstPath = new(at); + firstPath.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false); + + at.InitSplines(firstPath.GetPath()); + } + + public override void OnUpdate(uint diff) + { + _scheduler.Update(diff); + } + + public override void OnUnitEnter(Unit unit) + { + HandleUnitEnterExit(unit); + } + + public override void OnUnitExit(Unit unit) + { + // Note: this ensures any unit receives a second hit if they happen to be inside the At when Divine Star starts its return path. + HandleUnitEnterExit(unit); + } + + void HandleUnitEnterExit(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster == null) + return; + + if (_affectedUnits.Contains(unit.GetGUID())) + return; + + TriggerCastFlags triggerFlags = TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress; + + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, at.GetSpellId() == SpellIds.DivineStarShadow ? SpellIds.DivineStarShadowDamage : SpellIds.DivineStarHolyDamage, + triggerFlags); + else if (caster.IsValidAssistTarget(unit)) + caster.CastSpell(unit, at.GetSpellId() == SpellIds.DivineStarShadow ? SpellIds.DivineStarShadowHeal : SpellIds.DivineStarHolyHeal, + triggerFlags); + + _affectedUnits.Add(unit.GetGUID()); + } + + public override void OnDestinationReached() + { + Unit caster = at.GetCaster(); + if (caster == null) + return; + + if (at.GetDistance(_casterCurrentPosition) > 0.05f) { - SpellInfo spellInfo = SpellMgr.GetSpellInfo(at.GetSpellId(), Difficulty.None); - if (spellInfo == null) - return; + _affectedUnits.Clear(); - if (spellInfo.GetEffects().Count <= 1) - return; + ReturnToCaster(); + } + else + at.Remove(); + } + void ReturnToCaster() + { + _scheduler.Schedule(TimeSpan.FromSeconds(0), task => + { Unit caster = at.GetCaster(); if (caster == null) return; _casterCurrentPosition = caster.GetPosition(); - // Note: max. distance at which the Divine Star can travel to is 1's BasePoints yards. - float maxTravelDistance = (float)(spellInfo.GetEffect(1).CalcValue(caster)); + at.InitSplines([at, caster]); - Position destPos = _casterCurrentPosition; - at.MovePositionToFirstCollision(destPos, maxTravelDistance, 0.0f); - - PathGenerator firstPath = new(at); - firstPath.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false); - - at.InitSplines(firstPath.GetPath()); - } - - public override void OnUpdate(uint diff) - { - _scheduler.Update(diff); - } - - public override void OnUnitEnter(Unit unit) - { - HandleUnitEnterExit(unit); - } - - public override void OnUnitExit(Unit unit) - { - // Note: this ensures any unit receives a second hit if they happen to be inside the At when Divine Star starts its return path. - HandleUnitEnterExit(unit); - } - - void HandleUnitEnterExit(Unit unit) - { - Unit caster = at.GetCaster(); - if (caster == null) - return; - - if (_affectedUnits.Contains(unit.GetGUID())) - return; - - TriggerCastFlags TriggerFlags = TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress; - - if (caster.IsValidAttackTarget(unit)) - caster.CastSpell(unit, at.GetSpellId() == SpellIds.DivineStarShadow ? SpellIds.DivineStarShadowDamage : SpellIds.DivineStarHolyDamage, - TriggerFlags); - else if (caster.IsValidAssistTarget(unit)) - caster.CastSpell(unit, at.GetSpellId() == SpellIds.DivineStarShadow ? SpellIds.DivineStarShadowHeal : SpellIds.DivineStarHolyHeal, - TriggerFlags); - - _affectedUnits.Add(unit.GetGUID()); - } - - public override void OnDestinationReached() - { - Unit caster = at.GetCaster(); - if (caster == null) - return; - - if (at.GetDistance(_casterCurrentPosition) > 0.05f) - { - _affectedUnits.Clear(); - - ReturnToCaster(); - } - else - at.Remove(); - } - - void ReturnToCaster() - { - _scheduler.Schedule(TimeSpan.FromMilliseconds(0), task => - { - Unit caster = at.GetCaster(); - if (caster == null) - return; - - _casterCurrentPosition = caster.GetPosition(); - - Vector3[] returnSplinePoints = new Vector3[4]; - - returnSplinePoints[0] = at.GetPosition(); - returnSplinePoints[1] = caster.GetPosition(); - - at.InitSplines(returnSplinePoints); - - task.Repeat(TimeSpan.FromMilliseconds(250)); - }); - } + task.Repeat(TimeSpan.FromSeconds(250)); + }); } +} - [Script] // 391339 - Empowered Renew - class spell_pri_empowered_renew : AuraScript +[Script] // 391339 - Empowered Renew +class spell_pri_empowered_renew : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Renew, SpellIds.EmpoweredRenewHeal) + return ValidateSpellInfo(SpellIds.Renew, SpellIds.EmpoweredRenewHeal) && ValidateSpellEffect((SpellIds.Renew, 0)) - && SpellMgr.GetSpellInfo(SpellIds.Renew, Difficulty.None).GetEffect(0).IsAura(AuraType.PeriodicHeal); - } + && Global.SpellMgr.GetSpellInfo(SpellIds.Renew, Difficulty.None).GetEffect(0).IsAura(AuraType.PeriodicHeal); + } - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + SpellInfo renewSpellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.Renew, GetCastDifficulty()); + SpellEffectInfo renewEffect = renewSpellInfo.GetEffect(0); + int estimatedTotalHeal = (int)AuraEffect.CalculateEstimatedfTotalPeriodicAmount(caster, target, renewSpellInfo, renewEffect, renewEffect.CalcValue(caster), 1); + int healAmount = MathFunctions.CalculatePct(estimatedTotalHeal, aurEff.GetAmount()); + + caster.CastSpell(target, SpellIds.EmpoweredRenewHeal, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, healAmount)); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 414553 - Epiphany +class spell_pri_epiphany : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMending, SpellIds.EpiphanyHighlight); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + + target.GetSpellHistory().ResetCooldown(SpellIds.PrayerOfMending, true); + + target.CastSpell(target, SpellIds.EpiphanyHighlight, aurEff); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); + } +} + +// 415673 - Essence Devourer (Heal) +[Script] // 415676 - Essence Devourer (Heal) +class spell_pri_essence_devourer_heal : SpellScript +{ + void FilterTargets(List targets) + { + SelectRandomInjuredTargets(targets, 1, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +[Script] // 246287 - Evangelism +class spell_pri_evangelism : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Trinity, SpellIds.AtonementEffect, SpellIds.TrinityEffect); + } + + void HandleScriptEffect(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + Aura atonementAura = caster.HasAura(SpellIds.Trinity) + ? target.GetAura(SpellIds.TrinityEffect, caster.GetGUID()) + : target.GetAura(SpellIds.AtonementEffect, caster.GetGUID()); + if (atonementAura == null) + return; + + TimeSpan extraDuration = TimeSpan.FromSeconds(GetEffectValue()); + + atonementAura.SetDuration(atonementAura.GetDuration() + (int)extraDuration.TotalMilliseconds); + atonementAura.SetMaxDuration(atonementAura.GetDuration() + (int)extraDuration.TotalMilliseconds); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 33110 - Prayer of Mending (Heal) +class spell_pri_focused_mending : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.FocusedMending, 0)); + } + + void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) + { + AuraEffect focusedMendingEffect = GetCaster().GetAuraEffect(SpellIds.FocusedMending, 0); + if (focusedMendingEffect != null) { - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - SpellInfo renewSpellInfo = SpellMgr.GetSpellInfo(SpellIds.Renew, GetCastDifficulty()); - SpellEffectInfo renewEffect = renewSpellInfo.GetEffect(0); - int estimatedTotalHeal = (int)AuraEffect.CalculateEstimatedfTotalPeriodicAmount(caster, target, renewSpellInfo, renewEffect, renewEffect.CalcValue(caster), 1); - int healAmount = MathFunctions.CalculatePct(estimatedTotalHeal, aurEff.GetAmount()); - - caster.CastSpell(target, SpellIds.EmpoweredRenewHeal, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, healAmount)); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + if (GetSpell().m_customArg is bool isEmpoweredByFocusedMending && isEmpoweredByFocusedMending) + MathFunctions.AddPct(ref pctMod, focusedMendingEffect.GetAmount()); } } - [Script] // 414553 - Epiphany - class spell_pri_epiphany : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PrayerOfMending, SpellIds.EpiphanyHighlight); - } + CalcHealing.Add(new(CalculateHealingBonus)); + } +} - static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(aurEff.GetAmount()); - } - - void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit target = GetTarget(); - - target.GetSpellHistory().ResetCooldown(SpellIds.PrayerOfMending, true); - - target.CastSpell(target, SpellIds.EpiphanyHighlight, aurEff); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); - } +[Script] // 390615 - From Darkness Comes Light (Talent) +class spell_pri_from_darkness_comes_light : AuraScript +{ + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(GetTarget(), SpellIds.FromDarknessComesLightAura, aurEff); } - // 415673 - Essence Devourer (Heal) - [Script] // 415676 - Essence Devourer (Heal) - class spell_pri_essence_devourer_heal : SpellScript + public override void Register() { - void FilterTargets(List targets) - { - SelectRandomInjuredTargets(targets, 1, true); - } + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - } +[Script] // 47788 - Guardian Spirit +class spell_pri_guardian_spirit : AuraScript +{ + uint healPct = 0; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GuardianSpiritHeal) && ValidateSpellEffect((spellInfo.Id, 1)); } - [Script] // 246287 - Evangelism - class spell_pri_evangelism : SpellScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) + healPct = (uint)GetEffectInfo(1).CalcValue(); + return true; + } + + static void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + // Set absorbtion amount to unlimited + amount = -1; + } + + void Absorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + Unit target = GetTarget(); + if (dmgInfo.GetDamage() < target.GetHealth()) + return; + + int healAmount = (int)target.CountPctFromMaxHealth((int)healPct); + // remove the aura now, we don't want 40% healing bonus + Remove(AuraRemoveMode.EnemySpell); + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.AddSpellMod(SpellValueMod.BasePoint0, healAmount); + target.CastSpell(target, SpellIds.GuardianSpiritHeal, args); + absorbAmount = dmgInfo.GetDamage(); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.SchoolAbsorb)); + OnEffectAbsorb.Add(new(Absorb, 1)); + } +} + +[Script] // 421558 - Heaven's Wrath +class spell_pri_heavens_wrath : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UltimatePenitence); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + return !(eventInfo.GetSpellInfo().Id == SpellIds.UltimatePenitenceDamage || eventInfo.GetSpellInfo().Id == SpellIds.UltimatePenitenceHeal); + } + + static void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = eventInfo.GetActor(); + if (caster == null) + return; + + int cdReduction = aurEff.GetAmount(); + caster.GetSpellHistory().ModifyCooldown(SpellIds.UltimatePenitence, TimeSpan.FromSeconds(-cdReduction), true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 120644 - Halo (Shadow) +class spell_pri_halo_shadow : SpellScript +{ + void HandleHitTarget(uint effIndex) + { + Unit caster = GetCaster(); + + if ((int)caster.GetPowerType() != GetEffectInfo().MiscValue) + PreventHitDefaultEffect(effIndex); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHitTarget, 1, SpellEffectName.Energize)); + } +} + +// 120517 - Halo (Holy) +[Script] // 120644 - Halo (Shadow) +class areatrigger_pri_halo(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) { - return ValidateSpellInfo(SpellIds.Trinity, SpellIds.AtonementEffect, SpellIds.TrinityEffect); + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, at.GetSpellId() == SpellIds.HaloShadow ? SpellIds.HaloShadowDamage : SpellIds.HaloHolyDamage, + TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); + else if (caster.IsValidAssistTarget(unit)) + caster.CastSpell(unit, at.GetSpellId() == SpellIds.HaloShadow ? SpellIds.HaloShadowHeal : SpellIds.HaloHolyHeal, + TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); } + } +} - void HandleScriptEffect(uint effIndex) +[Script] // 391154 - Holy Mending +class spell_pri_holy_mending : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Renew, SpellIds.HolyMendingHeal); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + return procInfo.GetProcTarget().HasAura(SpellIds.Renew, procInfo.GetActor().GetGUID()); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.HolyMendingHeal, new CastSpellExtraArgs(aurEff)); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 63733 - Holy Words +class spell_pri_holy_words : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo( + SpellIds.Heal, + SpellIds.FlashHeal, + SpellIds.PrayerOfHealing, + SpellIds.Renew, + SpellIds.Smite, + SpellIds.HolyWordChastise, + SpellIds.HolyWordSanctify, + SpellIds.HolyWordSerenity + ) && ValidateSpellEffect((SpellIds.HolyWordSerenity, 1), (SpellIds.HolyWordSanctify, 3), (SpellIds.HolyWordChastise, 1)); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null) + return; + + uint targetSpellId; + uint cdReductionEffIndex; + switch (spellInfo.Id) { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - Aura atonementAura = caster.HasAura(SpellIds.Trinity) - ? target.GetAura(SpellIds.TrinityEffect, caster.GetGUID()) - : target.GetAura(SpellIds.AtonementEffect, caster.GetGUID()); - if (atonementAura == null) + case SpellIds.Heal: + case SpellIds.FlashHeal: // reduce Holy Word: Serenity cd by 6 seconds + targetSpellId = SpellIds.HolyWordSerenity; + cdReductionEffIndex = 1; + // cdReduction = Global.SpellMgr.GetSpellInfo(SpellIds.HolyWordSerenity, GetCastDifficulty()).GetEffect(1).CalcValue(player); + break; + case SpellIds.PrayerOfHealing: // reduce Holy Word: Sanctify cd by 6 seconds + targetSpellId = SpellIds.HolyWordSanctify; + cdReductionEffIndex = 2; + break; + case SpellIds.Renew: // reuce Holy Word: Sanctify cd by 2 seconds + targetSpellId = SpellIds.HolyWordSanctify; + cdReductionEffIndex = 3; + break; + case SpellIds.Smite: // reduce Holy Word: Chastise cd by 4 seconds + targetSpellId = SpellIds.HolyWordChastise; + cdReductionEffIndex = 1; + break; + default: + Log.outWarn(LogFilter.Spells, $"HolyWords aura has been proced by an unknown spell: {GetSpellInfo().Id}"); return; - - TimeSpan extraDuration = TimeSpan.FromSeconds(GetEffectValue()); - - atonementAura.SetDuration((int)(atonementAura.GetDuration() + extraDuration.TotalMilliseconds)); - atonementAura.SetMaxDuration((int)(atonementAura.GetDuration() + extraDuration.TotalMilliseconds)); } - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } + SpellInfo targetSpellInfo = Global.SpellMgr.GetSpellInfo(targetSpellId, GetCastDifficulty()); + int cdReduction = targetSpellInfo.GetEffect(cdReductionEffIndex).CalcValue(GetTarget()); + GetTarget().GetSpellHistory().ModifyCooldown(targetSpellInfo, TimeSpan.FromSeconds(-cdReduction), true); } - [Script] // 33110 - Prayer of Mending (Heal) - class spell_pri_focused_mending : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.FocusedMending, 0)); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) - { - AuraEffect focusedMendingEffect = GetCaster().GetAuraEffect(SpellIds.FocusedMending, 0); - if (focusedMendingEffect != null) - { - bool isEmpoweredByFocusedMending = (bool)GetSpell().m_customArg; - - if (isEmpoweredByFocusedMending && isEmpoweredByFocusedMending) - MathFunctions.AddPct(ref pctMod, focusedMendingEffect.GetAmount()); - } - } - - public override void Register() - { - CalcHealing.Add(new(CalculateHealingBonus)); - } +[Script] // 265202 - Holy Word: Salvation +class spell_pri_holy_word_salvation : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMendingAura, SpellIds.Renew) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0), (spellInfo.Id, 1)) + && spellInfo.GetEffect(1).TargetB.GetTarget() == Targets.UnitSrcAreaAlly; } - [Script] // 390615 - From Darkness Comes Light (Talent) - class spell_pri_from_darkness_comes_light : AuraScript + public override bool Load() { - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().CastSpell(GetTarget(), SpellIds.FromDarknessComesLightAura, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } + _spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); + _healEffectDummy = _spellInfoHeal.GetEffect(0); + return true; } - [Script] // 47788 - Guardian Spirit - class spell_pri_guardian_spirit : AuraScript + void HandleApplyBuffs(uint effIndex) { - uint healPct; + Unit caster = GetCaster(); + Unit target = GetHitUnit(); - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GuardianSpiritHeal) && ValidateSpellEffect((spellInfo.Id, 1)); - } + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; - public override bool Load() - { - healPct = (uint)GetEffectInfo(1).CalcValue(); - return true; - } + // amount of Prayer of Mending is SpellIds.HolyWordSalvation's 1. + args.AddSpellMod(SpellValueMod.AuraStack, GetEffectValue()); - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - // Set absorbtion amount to unlimited - amount = -1; - } + int basePoints = caster.SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy.CalcValue(caster), DamageEffectType.Heal, _healEffectDummy); + args.AddSpellMod(SpellValueMod.BasePoint0, basePoints); + caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args); - void Absorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - Unit target = GetTarget(); - if (dmgInfo.GetDamage() < target.GetHealth()) - return; - - int healAmount = (int)target.CountPctFromMaxHealth((int)healPct); - // Remove the aura now, we don't want 40% healing bonus - Remove(AuraRemoveMode.EnemySpell); - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, healAmount); - target.CastSpell(target, SpellIds.GuardianSpiritHeal, args); - absorbAmount = dmgInfo.GetDamage(); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.SchoolAbsorb)); - OnEffectAbsorb.Add(new(Absorb, 1)); - } + // a full duration Renew is triggered. + caster.CastSpell(target, SpellIds.Renew, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetTriggeringSpell(GetSpell())); } - [Script] // 421558 - Heaven's Wrath - class spell_pri_heavens_wrath : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.UltimatePenitence); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return !(eventInfo.GetSpellInfo().Id == SpellIds.UltimatePenitenceDamage || eventInfo.GetSpellInfo().Id == SpellIds.UltimatePenitenceHeal); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = eventInfo.GetActor(); - if (caster == null) - return; - - int cdReduction = aurEff.GetAmount(); - caster.GetSpellHistory().ModifyCooldown(SpellIds.UltimatePenitence, TimeSpan.FromSeconds(-cdReduction), true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } + OnEffectHitTarget.Add(new(HandleApplyBuffs, 1, SpellEffectName.Dummy)); } - [Script] // 120644 - Halo (Shadow) - class spell_pri_halo_shadow : SpellScript + SpellInfo _spellInfoHeal = null; + SpellEffectInfo _healEffectDummy = null; +} + +// 2050 - Holy Word: Serenity +[Script] // 34861 - Holy Word: Sanctify +class spell_pri_holy_word_salvation_cooldown_reduction : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - void HandleHitTarget(uint effIndex) - { - Unit caster = GetCaster(); - - if (caster.GetPowerType() != (PowerType)GetEffectInfo().MiscValue) - PreventHitDefaultEffect(effIndex); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHitTarget, 1, SpellEffectName.Energize)); - } - } - - // 120517 - Halo (Holy) - [Script] // 120644 - Halo (Shadow) - class areatrigger_pri_halo : AreaTriggerAI - { - public areatrigger_pri_halo(AreaTrigger areatrigger) : base(areatrigger) { } - - public override void OnUnitEnter(Unit unit) - { - Unit caster = at.GetCaster(); - if (caster != null) - { - if (caster.IsValidAttackTarget(unit)) - caster.CastSpell(unit, at.GetSpellId() == SpellIds.HaloShadow ? SpellIds.HaloShadowDamage : SpellIds.HaloHolyDamage, - TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); - else if (caster.IsValidAssistTarget(unit)) - caster.CastSpell(unit, at.GetSpellId() == SpellIds.HaloShadow ? SpellIds.HaloShadowHeal : SpellIds.HaloHolyHeal, - TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); - } - } - } - - [Script] // 391154 - Holy Mending - class spell_pri_holy_mending : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Renew, SpellIds.HolyMendingHeal); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - return procInfo.GetProcTarget().HasAura(SpellIds.Renew, procInfo.GetActor().GetGUID()); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.HolyMendingHeal, new CastSpellExtraArgs(aurEff)); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 63733 - Holy Words - class spell_pri_holy_words : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Heal, SpellIds.FlashHeal, SpellIds.PrayerOfHealing, SpellIds.Renew, SpellIds.Smite, SpellIds.HolyWordChastise, SpellIds.HolyWordSanctify, SpellIds.HolyWordSerenity) - && ValidateSpellEffect((SpellIds.HolyWordSerenity, 1), (SpellIds.HolyWordSanctify, 3), (SpellIds.HolyWordChastise, 1)); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null) - return; - - uint targetSpellId; - uint cdReductionEffIndex; - switch (spellInfo.Id) - { - case SpellIds.Heal: - case SpellIds.FlashHeal: // reduce Holy Word: Serenity cd by 6 seconds - targetSpellId = SpellIds.HolyWordSerenity; - cdReductionEffIndex = 1; - // cdReduction = SpellMgr.GetSpellInfo(SpellIds.HolyWordSerenity, GetCastDifficulty()).GetEffect(1).CalcValue(player); - break; - case SpellIds.PrayerOfHealing: // reduce Holy Word: Sanctify cd by 6 seconds - targetSpellId = SpellIds.HolyWordSanctify; - cdReductionEffIndex = 2; - break; - case SpellIds.Renew: // reuce Holy Word: Sanctify cd by 2 seconds - targetSpellId = SpellIds.HolyWordSanctify; - cdReductionEffIndex = 3; - break; - case SpellIds.Smite: // reduce Holy Word: Chastise cd by 4 seconds - targetSpellId = SpellIds.HolyWordChastise; - cdReductionEffIndex = 1; - break; - default: - Log.outWarn(LogFilter.Spells, $"HolyWords aura has been proced by an unknown spell: {GetSpellInfo().Id}"); - return; - } - - SpellInfo targetSpellInfo = SpellMgr.GetSpellInfo(targetSpellId, GetCastDifficulty()); - int cdReduction = targetSpellInfo.GetEffect(cdReductionEffIndex).CalcValue(GetTarget()); - GetTarget().GetSpellHistory().ModifyCooldown(targetSpellInfo, TimeSpan.FromSeconds(-cdReduction), true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 265202 - Holy Word: Salvation - class spell_pri_holy_word_salvation : SpellScript - { - SpellInfo _spellInfoHeal; - SpellEffectInfo _healEffectDummy; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PrayerOfMendingAura, SpellIds.Renew) - && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0), (spellInfo.Id, 1)) - && spellInfo.GetEffect(1).TargetB.GetTarget() == Targets.UnitSrcAreaAlly; - } - - public override bool Load() - { - _spellInfoHeal = SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); - _healEffectDummy = _spellInfoHeal.GetEffect(0); - return true; - } - - void HandleApplyBuffs(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - - // amount of Prayer of Mending is SpellIds.HolyWordSalvation's 1. - args.AddSpellMod(SpellValueMod.AuraStack, GetEffectValue()); - - int basePoints = caster.SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy.CalcValue(caster), DamageEffectType.Heal, _healEffectDummy); - args.AddSpellMod(SpellValueMod.BasePoint0, basePoints); - caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args); - - // a full duration Renew is triggered. - caster.CastSpell(target, SpellIds.Renew, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetTriggeringSpell(GetSpell())); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleApplyBuffs, 1, SpellEffectName.Dummy)); - } - } - - // 2050 - Holy Word: Serenity - [Script] // 34861 - Holy Word: Sanctify - class spell_pri_holy_word_salvation_cooldown_reduction : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HolyWordSalvation) + return ValidateSpellInfo(SpellIds.HolyWordSalvation) && ValidateSpellEffect((SpellIds.HolyWordSalvation, 2)); - } - - public override bool Load() - { - return GetCaster().HasSpell(SpellIds.HolyWordSalvation); - } - - void ReduceCooldown() - { - // cooldown reduced by SpellIds.HolyWordSalvation's Seconds(2). - int cooldownReduction = SpellMgr.GetSpellInfo(SpellIds.HolyWordSalvation, GetCastDifficulty()).GetEffect(2).CalcValue(GetCaster()); - - GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.HolyWordSalvation, TimeSpan.FromSeconds(-cooldownReduction), true); - } - - public override void Register() - { - AfterCast.Add(new(ReduceCooldown)); - } } - [Script] // 40438 - Priest Tier 6 Trinket - class spell_pri_item_t6_trinket : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DivineBlessing, SpellIds.DivineWrath); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - if ((eventInfo.GetSpellTypeMask() & ProcFlagsSpellType.Heal) != 0) - caster.CastSpell(null, SpellIds.DivineBlessing, true); - - if ((eventInfo.GetSpellTypeMask() & ProcFlagsSpellType.Damage) != 0) - caster.CastSpell(null, SpellIds.DivineWrath, true); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + return GetCaster().HasSpell(SpellIds.HolyWordSalvation); } - [Script] // 92833 - Leap of Faith - class spell_pri_leap_of_faith_effect_trigger : SpellScript + void ReduceCooldown() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LeapOfFaithEffect); - } + // cooldown reduced by SpellIds.HolyWordSalvation's TimeSpan.FromSeconds(2). + int cooldownReduction = Global.SpellMgr.GetSpellInfo(SpellIds.HolyWordSalvation, GetCastDifficulty()).GetEffect(2).CalcValue(GetCaster()); - void HandleEffectDummy(uint effIndex) - { - Position destPos = GetHitDest().GetPosition(); - - SpellCastTargets targets = new(); - targets.SetDst(destPos); - targets.SetUnitTarget(GetCaster()); - GetHitUnit().CastSpell(targets, (uint)GetEffectValue(), GetCastDifficulty()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); - } + GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.HolyWordSalvation, TimeSpan.FromSeconds(-cooldownReduction), true); } - [Script] // 1706 - Levitate - class spell_pri_levitate : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LevitateEffect); - } + AfterCast.Add(new(ReduceCooldown)); + } +} - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.LevitateEffect, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } +[Script] // 40438 - Priest Tier 6 Trinket +class spell_pri_item_t6_trinket : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DivineBlessing, SpellIds.DivineWrath); } - [Script] // 373178 - Light's Wrath - class spell_pri_lights_wrath : SpellScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + if ((eventInfo.GetSpellTypeMask() & ProcFlagsSpellType.Heal) != 0) + caster.CastSpell(null, SpellIds.DivineBlessing, true); + + if ((eventInfo.GetSpellTypeMask() & ProcFlagsSpellType.Damage) != 0) + caster.CastSpell(null, SpellIds.DivineWrath, true); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 92833 - Leap of Faith +class spell_pri_leap_of_faith_effect_trigger : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LeapOfFaithEffect); + } + + void HandleEffectDummy(uint effIndex) + { + Position destPos = GetHitDest().GetPosition(); + + SpellCastTargets targets = new(); + targets.SetDst(destPos); + targets.SetUnitTarget(GetCaster()); + GetHitUnit().CastSpell(targets, (uint)GetEffectValue(), GetCastDifficulty()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 1706 - Levitate +class spell_pri_levitate : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LevitateEffect); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.LevitateEffect, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 373178 - Light's Wrath +class spell_pri_lights_wrath : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + public override void OnPrecast() + { + Aura atonement = GetCaster().GetAura(SpellIds.Atonement); + if (atonement == null) + return; + + spell_pri_atonement script = atonement.GetScript(); + if (script == null) + return; + + foreach (ObjectGuid atonementTarget in script.GetAtonementTargets()) { - return ValidateSpellEffect((spellInfo.Id, 1)); - } - - public override void OnPrecast() - { - Aura atonement = GetCaster().GetAura(SpellIds.Atonement); - if (atonement == null) - return; - - spell_pri_atonement script = atonement.GetScript(); - if (script == null) - return; - - foreach (ObjectGuid atonementTarget in script.GetAtonementTargets()) + Unit target = Global.ObjAccessor.GetUnit(GetCaster(), atonementTarget); + if (target != null) { - Unit target = ObjAccessor.GetUnit(GetCaster(), atonementTarget); - if (target != null) - { - target.CancelSpellMissiles(SpellIds.LightsWrathVisual, false, false); - target.CastSpell(GetCaster(), SpellIds.LightsWrathVisual, TriggerCastFlags.IgnoreCastInProgress); - } + target.CancelSpellMissiles(SpellIds.LightsWrathVisual, false, false); + target.CastSpell(GetCaster(), SpellIds.LightsWrathVisual, TriggerCastFlags.IgnoreCastInProgress); } } + } - void CalculateDamageBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + void CalculateDamageBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + Aura atonement = GetCaster().GetAura(SpellIds.Atonement); + if (atonement == null) + return; + + // Atonement size may have changed when missile hits, we need to take an updated count of Atonement applications. + spell_pri_atonement script = atonement.GetScript(); + if (script != null) + MathFunctions.AddPct(ref pctMod, GetEffectInfo(1).CalcValue(GetCaster()) * script.GetAtonementTargets().Count); + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamageBonus)); + } +} + +[Script] // 205369 - Mind Bomb +class spell_pri_mind_bomb : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MindBombStun); + } + + void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Death || GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) { - Aura atonement = GetCaster().GetAura(SpellIds.Atonement); - if (atonement == null) - return; - - // Atonement size may have changed when missile hits, we need to take an updated count of Atonement applications. - spell_pri_atonement script = atonement.GetScript(); - if (script != null) - MathFunctions.AddPct(ref pctMod, GetEffectInfo(1).CalcValue(GetCaster()) * script.GetAtonementTargets().Count); - } - - public override void Register() - { - CalcDamage.Add(new(CalculateDamageBonus)); + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget().GetPosition(), SpellIds.MindBombStun, true); } } - [Script] // 205369 - Mind Bomb - class spell_pri_mind_bomb : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MindBombStun); - } - - void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Death || GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(GetTarget().GetPosition(), SpellIds.MindBombStun, true); - } - } - - public override void Register() - { - AfterEffectRemove.Add(new(RemoveEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + AfterEffectRemove.Add(new(RemoveEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); } +} - // 373202 - Mind Devourer - [Script] // Triggered by 8092 - Mind Blast - class spell_pri_mind_devourer : SpellScript +// 373202 - Mind Devourer +[Script] // Triggered by 8092 - Mind Blast +class spell_pri_mind_devourer : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MindDevourerAura) + return ValidateSpellInfo(SpellIds.MindDevourerAura) && ValidateSpellEffect((SpellIds.MindDevourer, 0)); - } - - public override bool Load() - { - return GetCaster().HasAura(SpellIds.MindDevourer); - } - - void HandleEffectHitTarget(uint effIndex) - { - AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.MindDevourer, 0); - if (aurEff != null && RandomHelper.randChance(aurEff.GetAmount())) - GetCaster().CastSpell(GetCaster(), SpellIds.MindDevourerAura, GetSpell()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new EffectHandler(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage)); - } } - // 373204 - Mind Devourer (Aura) - [Script] // Attached to 335467 - Devouring Plague - class spell_pri_mind_devourer_buff_aura : AuraScript + public override bool Load() { - public float DamageIncrease; - - void CalculateDamage(AuraEffect aurEff, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - MathFunctions.AddPct(ref pctMod, DamageIncrease); - } - - public override void Register() - { - DoEffectCalcDamageAndHealing.Add(new EffectCalcDamageAndHealingHandler(CalculateDamage, 1, AuraType.PeriodicLeech)); - } + return GetCaster().HasAura(SpellIds.MindDevourer); } - [Script] - class spell_pri_mind_devourer_buff : SpellScript + void HandleEffectHitTarget(uint effIndex) { - float _damageIncrease; + AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.MindDevourer, 0); + if (aurEff != null && RandomHelper.randChance(aurEff.GetAmount())) + GetCaster().CastSpell(GetCaster(), SpellIds.MindDevourerAura, GetSpell()); + } - public override bool Validate(SpellInfo spellInfo) + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage)); + } +} + +// 373204 - Mind Devourer (Aura) +[Script] // Attached to 335467 - Devouring Plague +class spell_pri_mind_devourer_buff_aura : AuraScript +{ + public float DamageIncrease = 0.0f; + + void CalculateDamage(AuraEffect aurEff, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + MathFunctions.AddPct(ref pctMod, DamageIncrease); + } + + public override void Register() + { + DoEffectCalcDamageAndHealing.Add(new(CalculateDamage, 1, AuraType.PeriodicLeech)); + } +} + +[Script] +class spell_pri_mind_devourer_buff : SpellScript +{ + float _damageIncrease = 0.0f; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.MindDevourerAura, 1)); + } + + public override void OnPrecast() + { + AuraEffect mindDevourer = GetCaster().GetAuraEffect(SpellIds.MindDevourerAura, 1); + if (mindDevourer == null || !GetSpell().m_appliedMods.Contains(mindDevourer.GetBase())) + return; + + _damageIncrease = (int)mindDevourer.GetAmount(); + } + + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + MathFunctions.AddPct(ref pctMod, _damageIncrease); + } + + void ModifyAuraValueAndRemoveBuff(uint effIndex) + { + if (_damageIncrease == 0) + return; + + Aura devouringPlague = GetHitAura(); + if (devouringPlague != null) { - return ValidateSpellEffect((SpellIds.MindDevourerAura, 1)); - } - - public override void OnPrecast() - { - AuraEffect mindDevourer = GetCaster().GetAuraEffect(SpellIds.MindDevourerAura, 1); - if (mindDevourer == null || !GetSpell().m_appliedMods.Contains(mindDevourer.GetBase())) - return; - - _damageIncrease = mindDevourer.GetAmount(); - } - - void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - MathFunctions.AddPct(ref pctMod, _damageIncrease); - } - - void ModifyAuraValueAndRemoveBuff(uint effIndex) - { - if (_damageIncrease == 0) - return; - - Aura devouringPlague = GetHitAura(); - if (devouringPlague != null) - { - spell_pri_mind_devourer_buff_aura script = devouringPlague.GetScript(); + spell_pri_mind_devourer_buff_aura script = devouringPlague.GetScript(); + if (script != null) script.DamageIncrease = _damageIncrease; - } - - GetCaster().RemoveAurasDueToSpell(SpellIds.MindDevourerAura); } - public override void Register() - { - CalcDamage.Add(new DamageAndHealingCalcHandler(CalculateDamage)); - OnEffectHitTarget.Add(new EffectHandler(ModifyAuraValueAndRemoveBuff, 1, SpellEffectName.ApplyAura)); - } + GetCaster().RemoveAurasDueToSpell(SpellIds.MindDevourerAura); } - [Script] // 390686 - Painful Punishment - class spell_pri_painful_punishment : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ShadowWordPain, SpellIds.PurgeTheWickedPeriodic); - } + CalcDamage.Add(new(CalculateDamage)); + OnEffectHitTarget.Add(new(ModifyAuraValueAndRemoveBuff, 1, SpellEffectName.ApplyAura)); + } +} - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetActionTarget(); - if (caster == null || target == null) - return; - - int additionalDuration = aurEff.GetAmount(); - - Aura shadowWordPain = target.GetOwnedAura(SpellIds.ShadowWordPain, caster.GetGUID()); - if (shadowWordPain != null) - shadowWordPain.SetDuration(shadowWordPain.GetDuration() + additionalDuration); - - Aura purgeTheWicked = target.GetOwnedAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID()); - if (purgeTheWicked != null) - purgeTheWicked.SetDuration(purgeTheWicked.GetDuration() + additionalDuration); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } +[Script] // 390686 - Painful Punishment +class spell_pri_painful_punishment : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowWordPain, SpellIds.PurgeTheWickedPeriodic); } - // 372991 - Pain Transformation - [Script] // Triggered by 33206 - Pain Suppression - class spell_pri_pain_transformation : SpellScript + static void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.PainTransformation, SpellIds.PainTransformationHeal); - } + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetActionTarget(); + if (caster == null || target == null) + return; - public override bool Load() - { - return GetCaster().HasAura(SpellIds.PainTransformation) && !GetCaster().HasAura(SpellIds.Trinity); - } + int additionalDuration = aurEff.GetAmount(); - void HandleHit(uint effIndex) - { - CastSpellExtraArgs args = new(GetSpell()); - args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + Aura shadowWordPain = target.GetOwnedAura(SpellIds.ShadowWordPain, caster.GetGUID()); + if (shadowWordPain != null) + shadowWordPain.SetDuration(shadowWordPain.GetDuration() + additionalDuration); - GetCaster().CastSpell(GetHitUnit(), SpellIds.PainTransformationHeal, args); - GetCaster().CastSpell(GetHitUnit(), SpellIds.AtonementEffect, args); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.ApplyAura)); - } + Aura purgeTheWicked = target.GetOwnedAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID()); + if (purgeTheWicked != null) + purgeTheWicked.SetDuration(purgeTheWicked.GetDuration() + additionalDuration); } - [Script("spell_pri_penance", SpellIds.PenanceChannelDamage, SpellIds.PenanceChannelHealing)] // 47540 - Penance - [Script("spell_pri_dark_reprimand", SpellIds.DarkReprimandChannelDamage, SpellIds.DarkReprimandChannelHealing)] // 400169 - Dark Reprimand - class spell_pri_penance : SpellScript + public override void Register() { - uint _damageSpellId; - uint _healingSpellId; + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} - public spell_pri_penance(uint damageSpellId, uint healingSpellId) +// 372991 - Pain Transformation +[Script] // Triggered by 33206 - Pain Suppression +class spell_pri_pain_transformation : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.PainTransformation, SpellIds.PainTransformationHeal); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.PainTransformation) && !GetCaster().HasAura(SpellIds.Trinity); + } + + void HandleHit(uint effIndex) + { + CastSpellExtraArgs args = new(GetSpell()); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + + GetCaster().CastSpell(GetHitUnit(), SpellIds.PainTransformationHeal, args); + GetCaster().CastSpell(GetHitUnit(), SpellIds.AtonementEffect, args); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.ApplyAura)); + } +} + +// 47540 - Penance +// 400169 - Dark Reprimand +[Script("spell_pri_penance", SpellIds.PenanceChannelDamage, SpellIds.PenanceChannelHealing)] +[Script("spell_pri_dark_reprimand", SpellIds.DarkReprimandChannelDamage, SpellIds.DarkReprimandChannelHealing)] +class spell_pri_penance(uint damageSpellId, uint healingSpellId) : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(damageSpellId, healingSpellId); + } + + SpellCastResult CheckCast() + { + Unit caster = GetCaster(); + + Unit target = GetExplTargetUnit(); + if (target != null) { - _damageSpellId = damageSpellId; - _healingSpellId = healingSpellId; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_damageSpellId, _healingSpellId); - } - - SpellCastResult CheckCast() - { - Unit caster = GetCaster(); - - Unit target = GetExplTargetUnit(); - if (target != null) + if (!caster.IsFriendlyTo(target)) { - if (!caster.IsFriendlyTo(target)) - { - if (!caster.IsValidAttackTarget(target)) - return SpellCastResult.BadTargets; + if (!caster.IsValidAttackTarget(target)) + return SpellCastResult.BadTargets; - if (!caster.IsInFront(target)) - return SpellCastResult.UnitNotInfront; - } - } - - return SpellCastResult.SpellCastOk; - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - - Unit target = GetHitUnit(); - if (target != null) - { - if (caster.IsFriendlyTo(target)) - caster.CastSpell(target, _healingSpellId, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD) - .SetTriggeringSpell(GetSpell())); - else - caster.CastSpell(target, _damageSpellId, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD) - .SetTriggeringSpell(GetSpell())); + if (!caster.IsInFront(target)) + return SpellCastResult.UnitNotInfront; } } - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + return SpellCastResult.SpellCastOk; } - // 47758 - Penance (Channel Damage), 47757 - Penance (Channel Healing) - [Script] // 373129 - Dark Reprimand (Channel Damage), 400171 - Dark Reprimand (Channel Healing) - class spell_pri_penance_or_dark_reprimand_channeled : AuraScript + void HandleDummy(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) + Unit caster = GetCaster(); + + Unit target = GetHitUnit(); + if (target != null) { - return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide); - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - caster.RemoveAura(SpellIds.PowerOfTheDarkSide); - } - - public override void Register() - { - OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 114239 - Phantasm - class spell_pri_phantasm : SpellScript - { - void HandleEffectHit(uint effIndex) - { - GetCaster().RemoveMovementImpairingAuras(false); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffectHit, 0, SpellEffectName.Dummy)); - } - } - - // 262484 - Power Leech (Passive for Shadowfiend) - [Script] // 284621 - Power Leech (Passive for Mindbender) - class spell_pri_power_leech_passive : AuraScript - { - const uint NpcPriestMindbender = 62982; - const uint NpcPriestShadowfiend = 19668; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerLeechShadowfiendInsanity, SpellIds.PowerLeechShadowfiendMana, SpellIds.PowerLeechMindbenderInsanity, SpellIds.PowerLeechMindbenderMana, SpellIds.EssenceDevourer, SpellIds.EssenceDevourerShadowfiendHeal, SpellIds.EssenceDevourerMindbenderHeal) - && ValidateSpellEffect((SpellIds.PowerLeechShadowfiendInsanity, 0), (SpellIds.PowerLeechShadowfiendMana, 0), (SpellIds.PowerLeechMindbenderInsanity, 0), (SpellIds.PowerLeechMindbenderMana, 0)); - } - - static bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetDamageInfo() != null; - } - - void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit target = GetTarget(); - Player summoner = target.GetOwner()?.ToPlayer(); - if (summoner == null) - return; - - SpellInfo spellInfo; - int divisor = 1; - - if (summoner.GetPrimarySpecialization() != ChrSpecialization.PriestShadow) - { - if (target.GetEntry() == NpcPriestShadowfiend) - { - // Note: divisor is 100 because effect value is 5 and its supposed to restore 0.5% - spellInfo = SpellMgr.GetSpellInfo(SpellIds.PowerLeechShadowfiendMana, GetCastDifficulty()); - divisor = 10; - } - else - { - // Note: divisor is 100 because effect value is 20 and its supposed to restore 0.2% - spellInfo = SpellMgr.GetSpellInfo(SpellIds.PowerLeechMindbenderMana, GetCastDifficulty()); - divisor = 100; - } - } + if (caster.IsFriendlyTo(target)) + caster.CastSpell(target, healingSpellId, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD) + .SetTriggeringSpell(GetSpell())); else - spellInfo = SpellMgr.GetSpellInfo(target.GetEntry() == NpcPriestShadowfiend - ? SpellIds.PowerLeechShadowfiendInsanity - : SpellIds.PowerLeechMindbenderInsanity, GetCastDifficulty()); - - target.CastSpell(summoner, spellInfo.Id, new CastSpellExtraArgs(aurEff) - .AddSpellMod(SpellValueMod.BasePoint0, spellInfo.GetEffect(0).CalcValue() / divisor)); - - // Note: Essence Devourer talent. - if (summoner.HasAura(SpellIds.EssenceDevourer)) - summoner.CastSpell(null, target.GetEntry() == NpcPriestShadowfiend ? SpellIds.EssenceDevourerShadowfiendHeal : SpellIds.EssenceDevourerMindbenderHeal, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); - } - } - - [Script] // 198069 - Power of the Dark Side - class spell_pri_power_of_the_dark_side : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerOfTheDarkSideTint); - } - - void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, SpellIds.PowerOfTheDarkSideTint, true); - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - caster.RemoveAura(SpellIds.PowerOfTheDarkSideTint); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - // 47666 - Penance (Damage) - [Script] // 373130 - Dark Reprimand (Damage) - class spell_pri_power_of_the_dark_side_damage_bonus : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide); - } - - void CalculateDamageBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - AuraEffect powerOfTheDarkSide = GetCaster().GetAuraEffect(SpellIds.PowerOfTheDarkSide, 0); - if (powerOfTheDarkSide != null) - MathFunctions.AddPct(ref pctMod, powerOfTheDarkSide.GetAmount()); - } - - public override void Register() - { - CalcDamage.Add(new(CalculateDamageBonus)); - } - } - - // 47750 - Penance (Healing) - [Script] // 400187 - Dark Reprimand (Healing) - class spell_pri_power_of_the_dark_side_healing_bonus : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide); - } - - void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) - { - AuraEffect powerOfTheDarkSide = GetCaster().GetAuraEffect(SpellIds.PowerOfTheDarkSide, 0); - if (powerOfTheDarkSide != null) - MathFunctions.AddPct(ref pctMod, powerOfTheDarkSide.GetAmount()); - } - - public override void Register() - { - CalcHealing.Add(new(CalculateHealingBonus)); - } - } - - [Script] // 194509 - Power Word: Radiance - class spell_pri_power_word_radiance : SpellScript - { - List _visualTargets = new(); - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.AtonementEffect); - } - - void FilterTargets(List targets) - { - Unit explTarget = GetExplTargetUnit(); - - // we must add one Math.Since explicit target is always chosen. - uint maxTargets = (uint)GetEffectInfo(2).CalcValue(GetCaster()) + 1; - - if (targets.Count > maxTargets) - { - // priority is: a) no Atonement b) injured c) anything else (excluding explicit target which is always added). - targets.Sort((lhs, rhs) => - { - if (lhs == explTarget) // explTarget > anything: always true - return 1; - if (rhs == explTarget) // anything > explTarget: always false - return -1; - - return MakeSortTuple(lhs).Equals(MakeSortTuple(rhs)) ? 1 : -1; - }); - - targets.Resize(maxTargets); - } - - foreach (WorldObject target in targets) - { - if (target == explTarget) - continue; - - _visualTargets.Add(target.GetGUID()); - } - } - - void HandleEffectHitTarget(uint effIndex) - { - foreach (ObjectGuid guid in _visualTargets) - { - Unit target = ObjAccessor.GetUnit(GetHitUnit(), guid); - if (target != null) - GetHitUnit().SendPlaySpellVisual(target, SpellIds.VisualPriestPowerWordRadiance, 0, 0, 70.0f); - } - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaAlly)); - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); - } - - (bool, bool) MakeSortTuple(WorldObject obj) - { - return (IsUnitWithNoAtonement(obj), IsUnitInjured(obj)); - } - - // Returns true if obj is a unit but has no atonement - bool IsUnitWithNoAtonement(WorldObject obj) - { - Unit unit = obj.ToUnit(); - return unit != null && !unit.HasAura(SpellIds.AtonementEffect, GetCaster().GetGUID()); - } - - // Returns true if obj is a unit and is injured - static bool IsUnitInjured(WorldObject obj) - { - Unit unit = obj.ToUnit(); - return unit != null && !unit.IsFullHealth(); - } - } - - [Script] // 17 - Power Word: Shield - class spell_pri_power_word_shield : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.StrengthOfSoul, SpellIds.StrengthOfSoulEffect, SpellIds.AtonementEffect, SpellIds.TrinityEffect, SpellIds.ShieldDiscipline, SpellIds.ShieldDisciplineEffect, SpellIds.PvpRulesEnabledHardcoded) - && ValidateSpellEffect((SpellIds.MasteryGrace, 0), (SpellIds.Rapture, 1), (SpellIds.Benevolence, 0), (SpellIds.DivineAegis, 1)); - } - - void CalculateAmount(AuraEffect auraEffect, ref int amount, ref bool canBeRecalculated) - { - canBeRecalculated = false; - - Unit caster = GetCaster(); - if (caster != null) - { - float modifiedAmount = caster.SpellBaseDamageBonusDone(GetSpellInfo().GetSchoolMask()) * 3.36f; - - Player player = caster.ToPlayer(); - if (player != null) - { - MathFunctions.AddPct(ref modifiedAmount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone)); - - // Mastery: Grace (Tbd: move into DoEffectCalcDamageAndHealing hook with a new SpellScript and AuraScript). - AuraEffect masteryGraceEffect = caster.GetAuraEffect(SpellIds.MasteryGrace, 0); - if (masteryGraceEffect != null) - if (GetUnitOwner().HasAura(SpellIds.AtonementEffect) || GetUnitOwner().HasAura(SpellIds.TrinityEffect)) - MathFunctions.AddPct(ref modifiedAmount, masteryGraceEffect.GetAmount()); - - switch (player.GetPrimarySpecialization()) - { - case ChrSpecialization.PriestDiscipline: - modifiedAmount *= 1.37f; - break; - case ChrSpecialization.PriestShadow: - modifiedAmount *= 1.25f; - if (caster.HasAura(SpellIds.PvpRulesEnabledHardcoded)) - modifiedAmount *= 0.8f; - break; - } - } - - float critChanceDone = caster.SpellCritChanceDone(null, auraEffect, GetSpellInfo().GetSchoolMask(), GetSpellInfo().GetAttackType()); - float critChanceTaken = GetUnitOwner().SpellCritChanceTaken(caster, null, auraEffect, GetSpellInfo().GetSchoolMask(), critChanceDone, GetSpellInfo().GetAttackType()); - - if (RandomHelper.randChance(critChanceTaken)) - { - modifiedAmount *= 2; - - // Divine Aegis - AuraEffect divineEff = caster.GetAuraEffect(SpellIds.DivineAegis, 1); - if (divineEff != null) - MathFunctions.AddPct(ref modifiedAmount, divineEff.GetAmount()); - } - - // Rapture talent (Tbd: move into DoEffectCalcDamageAndHealing hook). - AuraEffect raptureEffect = caster.GetAuraEffect(SpellIds.Rapture, 1); - if (raptureEffect != null) - MathFunctions.AddPct(ref modifiedAmount, raptureEffect.GetAmount()); - - // Benevolence talent - AuraEffect benevolenceEffect = caster.GetAuraEffect(SpellIds.Benevolence, 0); - if (benevolenceEffect != null) - MathFunctions.AddPct(ref modifiedAmount, benevolenceEffect.GetAmount()); - - amount = (int)modifiedAmount; - } - } - - void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - // Note: Strength of Soul PvP talent. - if (caster.HasAura(SpellIds.StrengthOfSoul)) - caster.CastSpell(GetTarget(), SpellIds.StrengthOfSoulEffect, aurEff); - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAura(SpellIds.StrengthOfSoulEffect); - - // Note: Shield Discipline talent. - Unit caster = GetCaster(); - if (caster != null) - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.EnemySpell && caster.HasAura(SpellIds.ShieldDiscipline)) - caster.CastSpell(caster, SpellIds.ShieldDisciplineEffect, aurEff); - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); - AfterEffectApply.Add(new(HandleOnApply, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.RealOrReapplyMask)); - AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.Real)); - } - } - - [Script] // 47515 - Divine Aegis - class spell_pri_divine_aegis : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.DivineAegisAbsorb, 0)); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetHealInfo() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = eventInfo.GetActor(); - if (caster == null) - return; - - int aegisAmount = (int)MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), aurEff.GetAmount()); - - CastSpellExtraArgs args = new(aurEff); - args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); - args.AddSpellMod(SpellValueMod.BasePoint0, aegisAmount); - caster.CastSpell(eventInfo.GetProcTarget(), SpellIds.DivineAegisAbsorb, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 129250 - Power Word: Solace - class spell_pri_power_word_solace : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerWordSolaceEnergize); - } - - void RestoreMana(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), SpellIds.PowerWordSolaceEnergize, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(GetSpell()) - .AddSpellMod(SpellValueMod.BasePoint0, GetEffectValue() / 100)); - } - - public override void Register() - { - OnEffectLaunch.Add(new(RestoreMana, 1, SpellEffectName.Dummy)); - } - } - - [Script] // 33076 - Prayer of Mending (Dummy) - class spell_pri_prayer_of_mending_dummy : SpellScript - { - SpellInfo _spellInfoHeal; - SpellEffectInfo _healEffectDummy; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura, SpellIds.PrayerOfMendingAura, SpellIds.Epiphany, SpellIds.EpiphanyHighlight) - && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0)); - } - - public override bool Load() - { - _spellInfoHeal = SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); - _healEffectDummy = _spellInfoHeal.GetEffect(0); - return true; - } - - void HandleEffectDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - // Note: we need to increase BasePoints by 1 Math.Since it's 4 as default. Also Hackfix, we shouldn't reduce it by 1 if the target has the aura already. - byte stackAmount = (byte)(target.HasAura(SpellIds.PrayerOfMendingAura, caster.GetGUID()) ? GetEffectValue() : GetEffectValue() + 1); - - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.AuraStack, stackAmount); - - // Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate. - int basePoints = caster.SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy.CalcValue(caster), DamageEffectType.Heal, _healEffectDummy); - args.AddSpellMod(SpellValueMod.BasePoint0, basePoints); - - // Note: Focused Mending talent. - args.SetCustomArg(true); - - caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args); - - // Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers. - caster.SendPlaySpellVisual(target, SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f); - - // Note: Epiphany talent. - if (caster.HasAura(SpellIds.Epiphany)) - caster.RemoveAurasDueToSpell(SpellIds.EpiphanyHighlight); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 41635 - Prayer of Mending (Aura) - class spell_pri_prayer_of_mending_AuraScript : AuraScript - { - bool _isEmpoweredByFocusedMending; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingJump) - && ValidateSpellEffect((SpellIds.SayYourPrayers, 0)); - } - - void HandleHeal(AuraEffect aurEff, ProcEventInfo eventInfo) - { - // Note: caster is the priest who cast the spell and target is current holder of the aura. - Unit target = GetTarget(); - - Unit caster = GetCaster(); - if (caster != null) - { - CastSpellExtraArgs args = new(aurEff); - args.SetCustomArg(_isEmpoweredByFocusedMending); - - caster.CastSpell(target, SpellIds.PrayerOfMendingHeal, args); - - // Note: jump is only executed if higher than 1 stack. - int stackAmount = GetStackAmount(); - if (stackAmount > 1) - { - args.OriginalCaster = caster.GetGUID(); - - int newStackAmount = stackAmount - 1; - AuraEffect sayYourPrayers = caster.GetAuraEffect(SpellIds.SayYourPrayers, 0); - if (sayYourPrayers != null) - if (RandomHelper.randChance(sayYourPrayers.GetAmount())) - ++newStackAmount; - - args.AddSpellMod(SpellValueMod.BasePoint0, newStackAmount); - - target.CastSpell(target, SpellIds.PrayerOfMendingJump, args); - } - - Remove(); - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleHeal, 0, AuraType.Dummy)); - } - - public void SetEmpoweredByFocusedMending(bool isEmpowered) - { - _isEmpoweredByFocusedMending = isEmpowered; - } - } - - [Script] - class spell_pri_prayer_of_mending : SpellScript - { - void HandleEffectDummy(uint effIndex) - { - Aura aura = GetHitAura(); - if (aura == null) - return; - - var script = aura.GetScript(); - if (script == null) - return; - - bool isEmpoweredByFocusedMending = (bool)GetSpell().m_customArg; - if (isEmpoweredByFocusedMending) - script.SetEmpoweredByFocusedMending(isEmpoweredByFocusedMending); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.ApplyAura)); - } - } - - [Script] // 155793 - Prayer of Mending (Jump) - class spell_pri_prayer_of_mending_jump : SpellScript - { - SpellInfo _spellInfoHeal; - SpellEffectInfo _healEffectDummy; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura) - && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0)); - } - - public override bool Load() - { - _spellInfoHeal = SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); - _healEffectDummy = _spellInfoHeal.GetEffect(0); - return true; - } - - void FilterTargets(List targets) - { - // Note: priority list is a) players b) non-player units. Also, this spell became smartheal in WoD. - SelectRandomInjuredTargets(targets, 1, true); - } - - void HandleJump(uint effIndex) - { - Unit origCaster = GetOriginalCaster(); - if (origCaster != null) - { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.AuraStack, (byte)GetEffectValue()); - - // Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate. - int basePoints = origCaster.SpellHealingBonusDone(GetHitUnit(), _spellInfoHeal, _healEffectDummy.CalcValue(origCaster), DamageEffectType.Heal, _healEffectDummy); - args.AddSpellMod(SpellValueMod.BasePoint0, basePoints); - - // Note: Focused Mending talent. - args.SetCustomArg(false); - - origCaster.CastSpell(GetHitUnit(), SpellIds.PrayerOfMendingAura, args); - - // Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers. - GetCaster().SendPlaySpellVisual(GetHitUnit(), SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f); - } - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaAlly)); - OnEffectHitTarget.Add(new(HandleJump, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 193063 - Protective Light (Aura) - class spell_pri_protective_light : AuraScript - { - bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget() == GetCaster(); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetCaster().CastSpell(GetCaster(), SpellIds.ProtectiveLightAura, aurEff); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - [Script] // 405554 - Priest Holy 10.1 Class Set 2pc - class spell_pri_holy_10_1_class_set_2pc : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Holy101ClassSet2PChooser) - && ValidateSpellEffect((SpellIds.PrayerOfMending, 0)); - } - - static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return RandomHelper.randChance(aurEff.GetAmount()); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - CastSpellExtraArgs args = new(aurEff); - args.SetTriggeringSpell(eventInfo.GetProcSpell()); - args.AddSpellMod(SpellValueMod.BasePoint0, SpellMgr.GetSpellInfo(SpellIds.PrayerOfMending, GetCastDifficulty()).GetEffect(0).CalcValue(GetCaster())); - - GetTarget().CastSpell(GetTarget(), SpellIds.Holy101ClassSet2PChooser, args); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 411097 - Priest Holy 10.1 Class Set 2pc (Chooser) - class spell_pri_holy_10_1_class_set_2pc_chooser : SpellScript - { - SpellInfo _spellInfoHeal; - SpellEffectInfo _healEffectDummy; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PrayerOfMendingAura, SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura) - && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0)); - } - - public override bool Load() - { - _spellInfoHeal = SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); - _healEffectDummy = _spellInfoHeal.GetEffect(0); - return true; - } - - void FilterTargets(List targets) - { - SelectRandomInjuredTargets(targets, 1, true); - } - - void HandleEffectDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - // Note: we need to increase BasePoints by 1 Math.Since it's 4 as default. Also Hackfix, we shouldn't reduce it by 1 if the target has the aura already. - byte stackAmount = (byte)(target.HasAura(SpellIds.PrayerOfMendingAura, caster.GetGUID()) ? GetEffectValue() : GetEffectValue() + 1); - - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.AuraStack, stackAmount); - - // Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate. - int basePoints = caster.SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy.CalcValue(caster), DamageEffectType.Heal, _healEffectDummy); - args.AddSpellMod(SpellValueMod.BasePoint0, basePoints); - - // Note: Focused Mending talent. - args.SetCustomArg(true); - - caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args); - - // Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers. - caster.SendPlaySpellVisual(target, SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEntry)); - OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 155793 - Prayer of Mending (Jump) - class spell_pri_holy_10_1_class_set_4pc : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Holy101ClassSet4P, SpellIds.Holy101ClassSet4PEffect); - } - - void HandleEffectDummy(uint effIndex) - { - if (GetOriginalCaster().HasAura(SpellIds.Holy101ClassSet4P)) - GetOriginalCaster().CastSpell(GetOriginalCaster(), SpellIds.Holy101ClassSet4PEffect, TriggerCastFlags.IgnoreGCD); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 41635 - Prayer of Mending (Aura) - class spell_pri_holy_10_1_class_set_4pc_AuraScript : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Holy101ClassSet4P, SpellIds.Holy101ClassSet4PEffect); - } - - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; - - if (GetCaster().HasAura(SpellIds.Holy101ClassSet4P)) - GetCaster().CastSpell(GetCaster(), SpellIds.Holy101ClassSet4PEffect, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD).SetTriggeringAura(aurEff)); - } - - public override void Register() - { - OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - // 204197 - Purge the Wicked - [Script] // Called by Penance - 47540, Dark Reprimand - 400169 - class spell_pri_purge_the_wicked : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PurgeTheWickedPeriodic, SpellIds.PurgeTheWickedDummy); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - if (target.HasAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID())) - caster.CastSpell(target, SpellIds.PurgeTheWickedDummy, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 204215 - Purge the Wicked - class spell_pri_purge_the_wicked_dummy : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PurgeTheWickedPeriodic, SpellIds.RevelInPurity) - && ValidateSpellEffect((SpellIds.RevelInPurity, 1)); - } - - void FilterTargets(List targets) - { - Unit caster = GetCaster(); - Unit explTarget = GetExplTargetUnit(); - - targets.RemoveAll(obj => - { - // Note: we must Remove any non-unit target, the explicit target and any other target that may be under any crowd control aura. - Unit target = obj.ToUnit(); - return target == null || target == explTarget || target.HasBreakableByDamageCrowdControlAura(); - }); - - if (targets.Empty()) - return; - - // Note: there's no SpellEffectDummy with BasePoints 1 in any of the spells related to use as reference so we hardcode the value. - uint spreadCount = 1; - - // Note: we must sort our list of targets whose priority is 1) aura, 2) distance, and 3) duration. - targets.Sort((lhs, rhs) => - { - Unit targetA = lhs.ToUnit(); - Unit targetB = rhs.ToUnit(); - - Aura auraA = targetA.GetAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID()); - Aura auraB = targetB.GetAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID()); - - if (auraA == null) - { - if (auraB != null) - return 1; - return explTarget.GetExactDist(targetA).CompareTo(explTarget.GetExactDist(targetB)); - } - if (auraB == null) - return -1; - - return auraA.GetDuration().CompareTo(auraB.GetDuration()); - }); - - // Note: Revel in Purity talent. - if (caster.HasAura(SpellIds.RevelInPurity)) - spreadCount += (uint)SpellMgr.GetSpellInfo(SpellIds.RevelInPurity, Difficulty.None).GetEffect(1).CalcValue(GetCaster()); - - if (targets.Count > spreadCount) - targets.Resize(spreadCount); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - - caster.CastSpell(target, SpellIds.PurgeTheWickedPeriodic, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); - } - } - - [Script] // 390622 - Rhapsody - class spell_pri_rhapsody : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.RhapsodyProc); - } - - void HandlePeriodic(AuraEffect aurEff) - { - Unit target = GetTarget(); - Aura rhapsodyStack = target.GetAura(SpellIds.RhapsodyProc, GetCasterGUID()); - if (rhapsodyStack != null) - rhapsodyStack.ModStackAmount(1); - else - target.CastSpell(target, SpellIds.RhapsodyProc, - new CastSpellExtraArgs(aurEff).SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.Dummy)); - } - } - - [Script] // 390636 - Rhapsody - class spell_pri_rhapsody_proc : AuraScript - { - void PreventChargeDrop(ProcEventInfo eventInfo) - { - PreventDefaultAction(); - } - - void RemoveAura(ProcEventInfo eventInfo) - { - // delay charge drop to allow spellmod to be applied to both damaging and healing spells - GetAura().DropChargeDelayed(1); - } - - public override void Register() - { - DoPrepareProc.Add(new(PreventChargeDrop)); - AfterProc.Add(new(RemoveAura)); - } - } - - [Script] // 47536 - Rapture - class spell_pri_rapture : SpellScript - { - ObjectGuid _raptureTarget; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerWordShield); - } - - void HandleEffectDummy(uint effIndex) - { - _raptureTarget = GetHitUnit().GetGUID(); - } - - void HandleAfterCast() - { - Unit caster = GetCaster(); - - Unit target = ObjAccessor.GetUnit(caster, _raptureTarget); - if (target != null) - caster.CastSpell(target, SpellIds.PowerWordShield, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress) + caster.CastSpell(target, damageSpellId, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD) .SetTriggeringSpell(GetSpell())); } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); - AfterCast.Add(new(HandleAfterCast)); - } } - [Script] // 8092 - Mind Blast - class spell_pri_schism : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Schism, SpellIds.SchismAura); - } + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - void HandleEffectHitTarget(uint effIndex) - { - if (GetCaster().HasAura(SpellIds.Schism)) - GetCaster().CastSpell(GetHitUnit(), SpellIds.SchismAura, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage)); - } +// 47758 - Penance (Channel Damage), 47757 - Penance (Channel Healing) +[Script] // 373129 - Dark Reprimand (Channel Damage), 400171 - Dark Reprimand (Channel Healing) +class spell_pri_penance_or_dark_reprimand_channeled : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide); } - [Script] // 208771 - Sanctuary (Absorb) - class spell_pri_sanctuary_absorb : AuraScript + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) + Unit caster = GetCaster(); + if (caster != null) + caster.RemoveAura(SpellIds.PowerOfTheDarkSide); + } + + public override void Register() + { + OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 114239 - Phantasm +class spell_pri_phantasm : SpellScript +{ + void HandleEffectHit(uint effIndex) + { + GetCaster().RemoveMovementImpairingAuras(false); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEffectHit, 0, SpellEffectName.Dummy)); + } +} + +// 262484 - Power Leech (Passive for Shadowfiend) +[Script] // 284621 - Power Leech (Passive for Mindbender) +class spell_pri_power_leech_passive : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerLeechShadowfiendInsanity, SpellIds.PowerLeechShadowfiendMana, SpellIds.PowerLeechMindbenderInsanity, SpellIds.PowerLeechMindbenderMana, SpellIds.EssenceDevourer, SpellIds.EssenceDevourerShadowfiendHeal, SpellIds.EssenceDevourerMindbenderHeal) + && ValidateSpellEffect((SpellIds.PowerLeechShadowfiendInsanity, 0), (SpellIds.PowerLeechShadowfiendMana, 0), (SpellIds.PowerLeechMindbenderInsanity, 0), (SpellIds.PowerLeechMindbenderMana, 0)); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo() != null; + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + Player summoner = target.GetOwner()?.ToPlayer(); + if (summoner == null) + return; + + SpellInfo spellInfo = null; + int divisor = 1; + + if (summoner.GetPrimarySpecialization() != ChrSpecialization.PriestShadow) { - return ValidateSpellInfo(SpellIds.SanctuaryAura); - } - - void CalcAbsorbAmount(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - PreventDefaultAction(); - - Unit attacker = dmgInfo.GetAttacker(); - if (attacker == null) - return; - - AuraEffect amountHolderEffect = attacker.GetAuraEffect(SpellIds.SanctuaryAura, 0, GetCasterGUID()); - if (amountHolderEffect == null) - return; - - if (dmgInfo.GetDamage() >= amountHolderEffect.GetAmount()) + if (target.GetEntry() == CreatureIds.Shadowfiend) { - amountHolderEffect.GetBase().Remove(AuraRemoveMode.EnemySpell); - dmgInfo.AbsorbDamage((uint)amountHolderEffect.GetAmount()); + // Note: divisor is 100 because effect value is 5 and its supposed to restore 0.5% + spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.PowerLeechShadowfiendMana, GetCastDifficulty()); + divisor = 10; } else { - amountHolderEffect.ChangeAmount((int)(amountHolderEffect.GetAmount() - dmgInfo.GetDamage())); - dmgInfo.AbsorbDamage(dmgInfo.GetDamage()); + // Note: divisor is 100 because effect value is 20 and its supposed to restore 0.2% + spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.PowerLeechMindbenderMana, GetCastDifficulty()); + divisor = 100; } } + else + spellInfo = Global.SpellMgr.GetSpellInfo(target.GetEntry() == CreatureIds.Shadowfiend + ? SpellIds.PowerLeechShadowfiendInsanity + : SpellIds.PowerLeechMindbenderInsanity, GetCastDifficulty()); - public override void Register() + target.CastSpell(summoner, spellInfo.Id, new CastSpellExtraArgs(aurEff) + .AddSpellMod(SpellValueMod.BasePoint0, spellInfo.GetEffect(0).CalcValue() / divisor)); + + // Note: Essence Devourer talent. + if (summoner.HasAura(SpellIds.EssenceDevourer)) + summoner.CastSpell(null, target.GetEntry() == CreatureIds.Shadowfiend ? SpellIds.EssenceDevourerShadowfiendHeal : SpellIds.EssenceDevourerMindbenderHeal, aurEff); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); + } +} + +[Script] // 198069 - Power of the Dark Side +class spell_pri_power_of_the_dark_side : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerOfTheDarkSideTint); + } + + void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.PowerOfTheDarkSideTint, true); + } + + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + caster.RemoveAura(SpellIds.PowerOfTheDarkSideTint); + } + + public override void Register() + { + OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +// 47666 - Penance (Damage) +[Script] // 373130 - Dark Reprimand (Damage) +class spell_pri_power_of_the_dark_side_damage_bonus : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide); + } + + void CalculateDamageBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + AuraEffect powerOfTheDarkSide = GetCaster().GetAuraEffect(SpellIds.PowerOfTheDarkSide, 0); + if (powerOfTheDarkSide != null) + MathFunctions.AddPct(ref pctMod, powerOfTheDarkSide.GetAmount()); + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamageBonus)); + } +} + +// 47750 - Penance (Healing) +[Script] // 400187 - Dark Reprimand (Healing) +class spell_pri_power_of_the_dark_side_healing_bonus : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide); + } + + void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) + { + AuraEffect powerOfTheDarkSide = GetCaster().GetAuraEffect(SpellIds.PowerOfTheDarkSide, 0); + if (powerOfTheDarkSide != null) + MathFunctions.AddPct(ref pctMod, powerOfTheDarkSide.GetAmount()); + } + + public override void Register() + { + CalcHealing.Add(new(CalculateHealingBonus)); + } +} + +[Script] // 194509 - Power Word: Radiance +class spell_pri_power_word_radiance : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AtonementEffect); + } + + void FilterTargets(List targets) + { + Unit explTarget = GetExplTargetUnit(); + + // we must add one since explicit target is always chosen. + uint maxTargets = (uint)GetEffectInfo(2).CalcValue(GetCaster()) + 1; + + if (targets.Count > maxTargets) { - OnEffectAbsorb.Add(new(CalcAbsorbAmount, 0)); + // priority is: a) no Atonement b) injured c) anything else (excluding explicit target which is always added). + targets.Sort((lhs, rhs) => + { + if (lhs == explTarget) // explTarget > anything: always true + return 1; + if (rhs == explTarget) // anything > explTarget: always false + return -1; + + return MakeSortTuple(lhs).Equals(MakeSortTuple(rhs)) ? 1 : -1; + }); + + targets.Resize(maxTargets); + } + + foreach (WorldObject target in targets) + { + if (target == explTarget) + continue; + + _visualTargets.Add(target.GetGUID()); } } - [Script] // Smite - 585 - class spell_pri_sanctuary_trigger : SpellScript + void HandleEffectHitTarget(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) + foreach (ObjectGuid guid in _visualTargets) { - return ValidateSpellInfo(SpellIds.Sanctuary, SpellIds.SanctuaryAura, SpellIds.SanctuaryAbsorb); + Unit target = Global.ObjAccessor.GetUnit(GetHitUnit(), guid); + if (target != null) + GetHitUnit().SendPlaySpellVisual(target, SpellIds.VisualPriestPowerWordRadiance, 0, 0, 70.0f); } + } - void HandleEffectHit(uint effIndex) + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaAlly)); + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); + } + + + (bool, bool) MakeSortTuple(WorldObject obj) + { + return (IsUnitWithNoAtonement(obj), IsUnitInjured(obj)); + } + + // Returns true if obj is a unit but has no atonement + bool IsUnitWithNoAtonement(WorldObject obj) + { + Unit unit = obj.ToUnit(); + return unit != null && !unit.HasAura(SpellIds.AtonementEffect, GetCaster().GetGUID()); + } + + // Returns true if obj is a unit and is injured + static bool IsUnitInjured(WorldObject obj) + { + Unit unit = obj.ToUnit(); + return unit != null && !unit.IsFullHealth(); + } + + List _visualTargets; +} + +[Script] // 17 - Power Word: Shield +class spell_pri_power_word_shield : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StrengthOfSoul, SpellIds.StrengthOfSoulEffect, SpellIds.AtonementEffect, SpellIds.TrinityEffect, SpellIds.ShieldDiscipline, SpellIds.ShieldDisciplineEffect, SpellIds.PvpRulesEnabledHardcoded) + && ValidateSpellEffect((SpellIds.MasteryGrace, 0), (SpellIds.Rapture, 1), (SpellIds.Benevolence, 0), (SpellIds.DivineAegis, 1)); + } + + void CalculateAmount(AuraEffect auraEffect, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = false; + + Unit caster = GetCaster(); + if (caster != null) { - Player caster = GetCaster()?.ToPlayer(); - if (caster == null) - return; + float modifiedAmount = caster.SpellBaseDamageBonusDone(GetSpellInfo().GetSchoolMask()) * 3.36f; - AuraEffect sanctuaryEffect = caster.GetAuraEffect(SpellIds.Sanctuary, 0); - if (sanctuaryEffect != null) + Player player = caster.ToPlayer(); + if (player != null) { - Unit target = GetHitUnit(); - if (target != null) + MathFunctions.AddPct(ref modifiedAmount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone)); + + // Mastery: Grace (Tbd: move into DoEffectCalcDamageAndHealing hook with a new SpellScript and AuraScript). + AuraEffect masteryGraceEffect = caster.GetAuraEffect(SpellIds.MasteryGrace, 0); + if (masteryGraceEffect != null) + if (GetUnitOwner().HasAura(SpellIds.AtonementEffect) || GetUnitOwner().HasAura(SpellIds.TrinityEffect)) + MathFunctions.AddPct(ref modifiedAmount, masteryGraceEffect.GetAmount()); + + switch (player.GetPrimarySpecialization()) { - float absorbAmount = MathFunctions.CalculatePct(caster.SpellBaseDamageBonusDone(SpellSchoolMask.Shadow), sanctuaryEffect.GetAmount()); - MathFunctions.AddPct(ref absorbAmount, caster.GetRatingBonusValue(CombatRating.VersatilityDamageDone)); - - caster.CastSpell(caster, SpellIds.SanctuaryAbsorb, new CastSpellExtraArgs() - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(GetSpell())); - - caster.CastSpell(target, SpellIds.SanctuaryAura, new CastSpellExtraArgs() - .AddSpellMod(SpellValueMod.BasePoint0, (int)absorbAmount) - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(GetSpell())); + case ChrSpecialization.PriestDiscipline: + modifiedAmount *= 1.37f; + break; + case ChrSpecialization.PriestShadow: + modifiedAmount *= 1.25f; + if (caster.HasAura(SpellIds.PvpRulesEnabledHardcoded)) + modifiedAmount *= 0.8f; + break; + default: + break; } } - } - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectHit, 0, SpellEffectName.SchoolDamage)); + float critChanceDone = caster.SpellCritChanceDone(null, auraEffect, GetSpellInfo().GetSchoolMask(), GetSpellInfo().GetAttackType()); + float critChanceTaken = GetUnitOwner().SpellCritChanceTaken(caster, null, auraEffect, GetSpellInfo().GetSchoolMask(), critChanceDone, GetSpellInfo().GetAttackType()); + + if (RandomHelper.randChance(critChanceTaken)) + { + modifiedAmount *= 2; + + // Divine Aegis + AuraEffect divineEff = caster.GetAuraEffect(SpellIds.DivineAegis, 1); + if (divineEff != null) + MathFunctions.AddPct(ref modifiedAmount, divineEff.GetAmount()); + } + + // Rapture talent (Tbd: move into DoEffectCalcDamageAndHealing hook). + AuraEffect raptureEffect = caster.GetAuraEffect(SpellIds.Rapture, 1); + if (raptureEffect != null) + MathFunctions.AddPct(ref modifiedAmount, raptureEffect.GetAmount()); + + // Benevolence talent + AuraEffect benevolenceEffect = caster.GetAuraEffect(SpellIds.Benevolence, 0); + if (benevolenceEffect != null) + MathFunctions.AddPct(ref modifiedAmount, benevolenceEffect.GetAmount()); + + amount = (int)modifiedAmount; } } - [Script] // 280391 - Sins of the Many - class spell_pri_Sins_of_the_many : AuraScript + void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SinsOfTheMany); - } + Unit caster = GetCaster(); + if (caster == null) + return; - void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().CastSpell(GetTarget(), SpellIds.SinsOfTheMany, true); - } + // Note: Strength of Soul PvP talent. + if (caster.HasAura(SpellIds.StrengthOfSoul)) + caster.CastSpell(GetTarget(), SpellIds.StrengthOfSoulEffect, aurEff); + } - void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAura(SpellIds.SinsOfTheMany); - } + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAura(SpellIds.StrengthOfSoulEffect); - public override void Register() + // Note: Shield Discipline talent. + Unit caster = GetCaster(); + if (caster != null) + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.EnemySpell && caster.HasAura(SpellIds.ShieldDiscipline)) + caster.CastSpell(caster, SpellIds.ShieldDisciplineEffect, aurEff); + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + AfterEffectApply.Add(new(HandleOnApply, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.RealOrReapplyMask)); + AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.Real)); + } +} + +[Script] // 47515 - Divine Aegis +class spell_pri_divine_aegis : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DivineAegisAbsorb, 0)); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetHealInfo() != null; + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = eventInfo.GetActor(); + if (caster == null) + return; + + int aegisAmount = (int)MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), aurEff.GetAmount()); + + CastSpellExtraArgs args = new(aurEff); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + args.AddSpellMod(SpellValueMod.BasePoint0, aegisAmount); + caster.CastSpell(eventInfo.GetProcTarget(), SpellIds.DivineAegisAbsorb, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 129250 - Power Word: Solace +class spell_pri_power_word_solace : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerWordSolaceEnergize); + } + + void RestoreMana(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.PowerWordSolaceEnergize, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(GetSpell()) + .AddSpellMod(SpellValueMod.BasePoint0, GetEffectValue() / 100)); + } + + public override void Register() + { + OnEffectLaunch.Add(new(RestoreMana, 1, SpellEffectName.Dummy)); + } +} + +[Script] // 33076 - Prayer of Mending (Dummy) +class spell_pri_prayer_of_mending_dummy : SpellScript +{ + SpellInfo _spellInfoHeal = null; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura, SpellIds.Epiphany, SpellIds.EpiphanyHighlight) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0)); + } + + public override bool Load() + { + _spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); + return true; + } + + void HandleEffectDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + // Note: we need to increase BasePoints by 1 since it's 4 as default. Also Hackfix, we shouldn't reduce it by 1 if the target has the aura already. + byte stackAmount = (byte)(target.HasAura(SpellIds.PrayerOfMendingAura, caster.GetGUID()) ? GetEffectValue() : GetEffectValue() + 1); + + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.AuraStack, stackAmount); + + // Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate. + SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0); + uint basePoints = (uint)caster.SpellHealingBonusDone(target, _spellInfoHeal, healEffectDummy.CalcValue(caster), DamageEffectType.Heal, healEffectDummy); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints); + + // Note: Focused Mending talent. + args.SetCustomArg(true); + + caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args); + + // Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers. + caster.SendPlaySpellVisual(target, SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f); + + // Note: Epiphany talent. + if (caster.HasAura(SpellIds.Epiphany)) + caster.RemoveAurasDueToSpell(SpellIds.EpiphanyHighlight); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 41635 - Prayer of Mending (Aura) +class spell_pri_prayer_of_mending_aura : AuraScript +{ + bool _isEmpoweredByFocusedMending; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingJump) + && ValidateSpellEffect((SpellIds.SayYourPrayers, 0)); + } + + void HandleHeal(AuraEffect aurEff, ProcEventInfo eventInfo) + { + // Note: caster is the priest who cast the spell and target is current holder of the aura. + Unit target = GetTarget(); + + Unit caster = GetCaster(); + if (caster != null) { - OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + CastSpellExtraArgs args = new(aurEff); + args.SetCustomArg(_isEmpoweredByFocusedMending); + + caster.CastSpell(target, SpellIds.PrayerOfMendingHeal, args); + + // Note: jump is only executed if higher than 1 stack. + int stackAmount = GetStackAmount(); + if (stackAmount > 1) + { + args.OriginalCaster = caster.GetGUID(); + + int newStackAmount = stackAmount - 1; + AuraEffect sayYourPrayers = caster.GetAuraEffect(SpellIds.SayYourPrayers, 0); + if (sayYourPrayers != null) + if (RandomHelper.randChance(sayYourPrayers.GetAmount())) + ++newStackAmount; + + args.AddSpellMod(SpellValueMod.BasePoint0, newStackAmount); + + target.CastSpell(target, SpellIds.PrayerOfMendingJump, args); + } + + Remove(); } } - [Script] // 20711 - Spirit of Redemption - class spell_pri_spirit_of_redemption : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SpiritOfRedemption); - } + OnEffectProc.Add(new(HandleHeal, 0, AuraType.Dummy)); + } - void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - Unit target = GetTarget(); - target.CastSpell(target, SpellIds.SpiritOfRedemption, aurEff); - target.SetFullHealth(); - } + public void SetEmpoweredByFocusedMending(bool isEmpowered) + { + _isEmpoweredByFocusedMending = isEmpowered; + } +} - public override void Register() +[Script] +class spell_pri_prayer_of_mending : SpellScript +{ + void HandleEffectDummy(uint effIndex) + { + Aura aura = GetHitAura(); + if (aura == null) + return; + + spell_pri_prayer_of_mending_aura script = aura.GetScript(); + if (script == null) + return; + + if (GetSpell().m_customArg is bool isEmpoweredByFocusedMending) + script.SetEmpoweredByFocusedMending(isEmpoweredByFocusedMending); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.ApplyAura)); + } +} + +[Script] // 155793 - Prayer of Mending (Jump) +class spell_pri_prayer_of_mending_jump : SpellScript +{ + SpellInfo _spellInfoHeal = null; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura) + && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0)); + } + + public override bool Load() + { + _spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); + return true; + } + + void FilterTargets(List targets) + { + SelectRandomInjuredTargets(targets, 1, true); + } + + void HandleJump(uint effIndex) + { + Unit origCaster = GetOriginalCaster(); + if (origCaster != null) { - OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.AuraStack, (byte)GetEffectValue()); + + // Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate. + SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0); + uint basePoints = (uint)origCaster.SpellHealingBonusDone(GetHitUnit(), _spellInfoHeal, healEffectDummy.CalcValue(origCaster), DamageEffectType.Heal, healEffectDummy); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints); + + // Note: Focused Mending talent. + args.SetCustomArg(false); + + origCaster.CastSpell(GetHitUnit(), SpellIds.PrayerOfMendingAura, args); + + // Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers. + GetCaster().SendPlaySpellVisual(GetHitUnit(), SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f); } } - [Script] // 314867 - Shadow Covenant - class spell_pri_shadow_covenant : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaAlly)); + OnEffectHitTarget.Add(new(HandleJump, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 193063 - Protective Light (Aura) +class spell_pri_protective_light : AuraScript +{ + bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget() == GetCaster(); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetCaster().CastSpell(GetCaster(), SpellIds.ProtectiveLightAura, aurEff); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 405554 - Priest Holy 10.1 Class Set 2pc +class spell_pri_holy_10_1_class_set_2pc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Holy10_1_ClassSet2PChooser) + && ValidateSpellEffect((SpellIds.PrayerOfMending, 0)); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + CastSpellExtraArgs args = new(aurEff); + args.SetTriggeringSpell(eventInfo.GetProcSpell()); + args.AddSpellMod(SpellValueMod.BasePoint0, Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMending, GetCastDifficulty()).GetEffect(0).CalcValue(GetCaster())); + + GetTarget().CastSpell(GetTarget(), SpellIds.Holy10_1_ClassSet2PChooser, args); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 411097 - Priest Holy 10.1 Class Set 2pc (Chooser) +class spell_pri_holy_10_1_class_set_2pc_chooser : SpellScript +{ + SpellInfo _spellInfoHeal = null; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0)); + } + + public override bool Load() + { + _spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); + return true; + } + + void FilterTargets(List targets) + { + SelectRandomInjuredTargets(targets, 1, true); + } + + void HandleEffectDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + // Note: we need to increase BasePoints by 1 since it's 4 as default. Also Hackfix, we shouldn't reduce it by 1 if the target has the aura already. + byte stackAmount = (byte)(target.HasAura(SpellIds.PrayerOfMendingAura, caster.GetGUID()) ? GetEffectValue() : GetEffectValue() + 1); + + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.AuraStack, stackAmount); + + // Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate. + SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0); + uint basePoints = (uint)caster.SpellHealingBonusDone(target, _spellInfoHeal, healEffectDummy.CalcValue(caster), DamageEffectType.Heal, healEffectDummy); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints); + + // Note: Focused Mending talent. + args.SetCustomArg(true); + + caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args); + + // Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers. + caster.SendPlaySpellVisual(target, SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEntry)); + OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 155793 - Prayer of Mending (Jump) +class spell_pri_holy_10_1_class_set_4pc : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Holy10_1_ClassSet4P, SpellIds.Holy10_1_ClassSet4PEffect); + } + + void HandleEffectDummy(uint effIndex) + { + if (GetOriginalCaster().HasAura(SpellIds.Holy10_1_ClassSet4P)) + GetOriginalCaster().CastSpell(GetOriginalCaster(), SpellIds.Holy10_1_ClassSet4PEffect, TriggerCastFlags.IgnoreGCD); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 41635 - Prayer of Mending (Aura) +class spell_pri_holy_10_1_class_set_4pc_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Holy10_1_ClassSet4P, SpellIds.Holy10_1_ClassSet4PEffect); + } + + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + if (GetCaster().HasAura(SpellIds.Holy10_1_ClassSet4P)) + GetCaster().CastSpell(GetCaster(), SpellIds.Holy10_1_ClassSet4PEffect, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD).SetTriggeringAura(aurEff)); + } + + public override void Register() + { + OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 17 - Power Word: Shield +class spell_pri_assured_safety : SpellScript +{ + SpellInfo _spellInfoHeal = null; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0), (SpellIds.AssuredSafety, 0)); + } + + public override bool Load() + { + _spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None); + return GetCaster().HasAura(SpellIds.AssuredSafety); + } + + void HandleEffectHitTarget(uint effIndex) + { + Unit caster = GetCaster(); + AuraEffect effect = caster.GetAuraEffect(SpellIds.AssuredSafety, 0); + if (effect != null) { - return ValidateSpellEffect((spellInfo.Id, 2)); - } + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.AuraStack, (byte)effect.GetAmount()); - void FilterTargets(List targets) - { - // Remove explicit target (will be readded later) - targets.Remove(GetExplTargetWorldObject()); + // Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate. + SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0); + uint basePoints = (uint)caster.SpellHealingBonusDone(GetHitUnit(), _spellInfoHeal, healEffectDummy.CalcValue(caster), DamageEffectType.Heal, healEffectDummy); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints); - // we must Remove one Math.Since explicit target is always added. - uint maxTargets = (uint)GetEffectInfo(2).CalcValue(GetCaster()) - 1; + // Note: Focused Mending talent. + args.SetCustomArg(false); - SelectRandomInjuredTargets(targets, maxTargets, true); + caster.CastSpell(GetHitUnit(), SpellIds.PrayerOfMendingAura, args); - Unit explicitTarget = GetExplTargetUnit(); - if (explicitTarget != null) - targets.Add(explicitTarget); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaAlly)); + // Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers. + caster.SendPlaySpellVisual(GetHitUnit(), SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f); } } - [Script] // 186263 - Shadow Mend - class spell_pri_shadow_mend : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Atonement, SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.MasochismTalent, SpellIds.MasochismPeriodicHeal, SpellIds.ShadowMendPeriodicDummy); - } + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.ApplyAura)); + } +} - void HandleEffectHit() +// 204197 - Purge the Wicked +[Script] // Called by Penance - 47540, Dark Reprimand - 400169 +class spell_pri_purge_the_wicked : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PurgeTheWickedPeriodic, SpellIds.PurgeTheWickedDummy); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + if (target.HasAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID())) + caster.CastSpell(target, SpellIds.PurgeTheWickedDummy, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 204215 - Purge the Wicked +class spell_pri_purge_the_wicked_dummy : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PurgeTheWickedPeriodic, SpellIds.RevelInPurity) + && ValidateSpellEffect((SpellIds.RevelInPurity, 1)); + } + + void FilterTargets(List targets) + { + Unit caster = GetCaster(); + Unit explTarget = GetExplTargetUnit(); + + targets.RemoveAll(obj => + { + // Note: we must remove any non-unit target, the explicit target and any other target that may be under any crowd control aura. + Unit target = obj.ToUnit(); + return target == null || target == explTarget || target.HasBreakableByDamageCrowdControlAura(); + }); + + if (targets.Empty()) + return; + + // Note: there's no SpellEffectName.Dummy with BasePoints 1 in any of the spells related to use as reference so we hardcode the value. + uint spreadCount = 1; + + // Note: we must sort our list of targets whose priority is 1) aura, 2) distance, and 3) duration. + targets.Sort((WorldObject lhs, WorldObject rhs) => + { + Unit targetA = lhs.ToUnit(); + Unit targetB = rhs.ToUnit(); + + Aura auraA = targetA.GetAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID()); + Aura auraB = targetB.GetAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID()); + + if (auraA == null) + { + if (auraB != null) + return 1; + return explTarget.GetExactDist(targetA).CompareTo(explTarget.GetExactDist(targetB)); + } + if (auraB == null) + return -1; + + return auraA.GetDuration().CompareTo(auraB.GetDuration()); + }); + + // Note: Revel in Purity talent. + if (caster.HasAura(SpellIds.RevelInPurity)) + spreadCount += (uint)Global.SpellMgr.GetSpellInfo(SpellIds.RevelInPurity, Difficulty.None).GetEffect(1).CalcValue(GetCaster()); + + if (targets.Count > spreadCount) + targets.Resize(spreadCount); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + caster.CastSpell(target, SpellIds.PurgeTheWickedPeriodic, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); + } +} + +[Script] // 390622 - Rhapsody +class spell_pri_rhapsody : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RhapsodyProc); + } + + void HandlePeriodic(AuraEffect aurEff) + { + Unit target = GetTarget(); + Aura rhapsodyStack = target.GetAura(SpellIds.RhapsodyProc, GetCasterGUID()); + if (rhapsodyStack != null) + rhapsodyStack.ModStackAmount(1); + else + target.CastSpell(target, SpellIds.RhapsodyProc, + new CastSpellExtraArgs(aurEff).SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 390636 - Rhapsody +class spell_pri_rhapsody_proc : AuraScript +{ + void PreventChargeDrop(ProcEventInfo eventInfo) + { + PreventDefaultAction(); + } + + void RemoveAura(ProcEventInfo eventInfo) + { + // delay charge drop to allow spellmod to be applied to both damaging and healing spells + GetAura().DropChargeDelayed(1); + } + + public override void Register() + { + DoPrepareProc.Add(new(PreventChargeDrop)); + AfterProc.Add(new(RemoveAura)); + } +} + +[Script] // 47536 - Rapture +class spell_pri_rapture : SpellScript +{ + ObjectGuid _raptureTarget; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerWordShield); + } + + void HandleEffectDummy(uint effIndex) + { + _raptureTarget = GetHitUnit().GetGUID(); + } + + void HandleAfterCast() + { + Unit caster = GetCaster(); + + Unit target = Global.ObjAccessor.GetUnit(caster, _raptureTarget); + if (target != null) + caster.CastSpell(target, SpellIds.PowerWordShield, + new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress) + .SetTriggeringSpell(GetSpell())); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 8092 - Mind Blast +class spell_pri_schism : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Schism, SpellIds.SchismAura); + } + + void HandleEffectHitTarget(uint effIndex) + { + if (GetCaster().HasAura(SpellIds.Schism)) + GetCaster().CastSpell(GetHitUnit(), SpellIds.SchismAura, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 208771 - Sanctuary (Absorb) +class spell_pri_sanctuary_absorb : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SanctuaryAura); + } + + void CalcAbsorbAmount(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + PreventDefaultAction(); + + Unit attacker = dmgInfo.GetAttacker(); + if (attacker == null) + return; + + AuraEffect amountHolderEffect = attacker.GetAuraEffect(SpellIds.SanctuaryAura, 0, GetCasterGUID()); + if (amountHolderEffect == null) + return; + + if (dmgInfo.GetDamage() >= amountHolderEffect.GetAmount()) + { + amountHolderEffect.GetBase().Remove(AuraRemoveMode.EnemySpell); + dmgInfo.AbsorbDamage((uint)amountHolderEffect.GetAmount()); + } + else + { + amountHolderEffect.ChangeAmount(amountHolderEffect.GetAmount() - (int)dmgInfo.GetDamage()); + dmgInfo.AbsorbDamage(dmgInfo.GetDamage()); + } + } + + public override void Register() + { + OnEffectAbsorb.Add(new(CalcAbsorbAmount, 0)); + } +} + +[Script] // Smite - 585 +class spell_pri_sanctuary_trigger : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Sanctuary, SpellIds.SanctuaryAura, SpellIds.SanctuaryAbsorb); + } + + void HandleEffectHit(uint effIndex) + { + Player caster = GetCaster()?.ToPlayer(); + if (caster == null) + return; + + AuraEffect sanctuaryEffect = caster.GetAuraEffect(SpellIds.Sanctuary, 0); + if (sanctuaryEffect != null) { Unit target = GetHitUnit(); if (target != null) { - Unit caster = GetCaster(); + float absorbAmount = MathFunctions.CalculatePct(caster.SpellBaseDamageBonusDone(SpellSchoolMask.Shadow), sanctuaryEffect.GetAmount()); + MathFunctions.AddPct(ref absorbAmount, caster.GetRatingBonusValue(CombatRating.VersatilityDamageDone)); - int periodicAmount = GetHitHeal() / 20; - int damageForAuraRemoveAmount = periodicAmount * 10; + caster.CastSpell(caster, SpellIds.SanctuaryAbsorb, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); - // Handle Masochism talent - if (caster.HasAura(SpellIds.MasochismTalent) && caster.GetGUID() == target.GetGUID()) - caster.CastSpell(caster, SpellIds.MasochismPeriodicHeal, new CastSpellExtraArgs(GetSpell()).AddSpellMod(SpellValueMod.BasePoint0, periodicAmount)); - else if (target.IsInCombat() && periodicAmount != 0) - { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.SetTriggeringSpell(GetSpell()); - args.AddSpellMod(SpellValueMod.BasePoint0, periodicAmount); - args.AddSpellMod(SpellValueMod.BasePoint1, damageForAuraRemoveAmount); - caster.CastSpell(target, SpellIds.ShadowMendPeriodicDummy, args); - } + caster.CastSpell(target, SpellIds.SanctuaryAura, new CastSpellExtraArgs() + .AddSpellMod(SpellValueMod.BasePoint0, (int)absorbAmount) + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); } } - - public override void Register() - { - AfterHit.Add(new(HandleEffectHit)); - } } - [Script] // 187464 - Shadow Mend (Damage) - class spell_pri_shadow_mend_periodic_damage : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ShadowMendDamage); - } + OnEffectHitTarget.Add(new(HandleEffectHit, 0, SpellEffectName.SchoolDamage)); + } +} - void HandleDummyTick(AuraEffect aurEff) - { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.SetOriginalCaster(GetCasterGUID()); - args.SetTriggeringAura(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount()); - GetTarget().CastSpell(GetTarget(), SpellIds.ShadowMendDamage, args); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetDamageInfo() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - int newAmount = (int)(aurEff.GetAmount() - eventInfo.GetDamageInfo().GetDamage()); - - aurEff.ChangeAmount(newAmount); - if (newAmount < 0) - Remove(); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy)); - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } +[Script] // 280391 - Sins of the Many +class spell_pri_sins_of_the_many : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SinsOfTheMany); } - // 32379 - Shadow Word: Death - class spell_pri_shadow_word_death : SpellScript + void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - static TimeSpan BACKLASH_DELAY = TimeSpan.FromSeconds(1); + GetTarget().CastSpell(GetTarget(), SpellIds.SinsOfTheMany, true); + } - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ShadowWordDeathDamage) - && ValidateSpellEffect((spellInfo.Id, 4)); - } + void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAura(SpellIds.SinsOfTheMany); + } - void HandleDamageCalculation(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - if (victim.HealthBelowPct(GetEffectInfo(1).CalcValue(GetCaster()))) - MathFunctions.AddPct(ref pctMod, GetEffectInfo(2).CalcValue(GetCaster())); - } + public override void Register() + { + OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - void DetermineKillStatus(DamageInfo damageInfo, ref uint resistAmount, ref int absorbAmount) +[Script] // 20711 - Spirit of Redemption +class spell_pri_spirit_of_redemption : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SpiritOfRedemption); + } + + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.SpiritOfRedemption, aurEff); + target.SetFullHealth(); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + } +} + +// 34433 - Shadowfiend +// 123040 - Mindbender (Discipline) +[Script] // 451235 - Voidwrath +class spell_pri_shadow_covenant : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowCovenant, SpellIds.ShadowCovenantEffect); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ShadowCovenant); + } + + void HandleAfterCast() + { + GetCaster().CastSpell(GetCaster(), SpellIds.ShadowCovenantEffect, new CastSpellExtraArgs() { - bool killed = damageInfo.GetDamage() >= damageInfo.GetVictim().GetHealth(); - if (!killed) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 186263 - Shadow Mend +class spell_pri_shadow_mend : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Atonement, SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.MasochismTalent, SpellIds.MasochismPeriodicHeal, SpellIds.ShadowMendPeriodicDummy); + } + + void HandleEffectHit() + { + Unit target = GetHitUnit(); + if (target != null) + { + Unit caster = GetCaster(); + + int periodicAmount = GetHitHeal() / 20; + int damageForAuraRemoveAmount = periodicAmount * 10; + + // Handle Masochism talent + if (caster.HasAura(SpellIds.MasochismTalent) && caster.GetGUID() == target.GetGUID()) + caster.CastSpell(caster, SpellIds.MasochismPeriodicHeal, new CastSpellExtraArgs(GetSpell()).AddSpellMod(SpellValueMod.BasePoint0, periodicAmount)); + else if (target.IsInCombat() && periodicAmount != 0) { - Unit caster = GetCaster(); - int backlashDamage = (int)caster.CountPctFromMaxHealth(GetEffectInfo(4).CalcValue(caster)); - var originalCastId = GetSpell().m_castId; - caster.m_Events.AddEventAtOffset(() => - { - caster.CastSpell(caster, SpellIds.ShadowWordDeathDamage, new CastSpellExtraArgs() - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetOriginalCastId(originalCastId) - .AddSpellMod(SpellValueMod.BasePoint0, backlashDamage)); - - }, BACKLASH_DELAY); + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.SetTriggeringSpell(GetSpell()); + args.AddSpellMod(SpellValueMod.BasePoint0, periodicAmount); + args.AddSpellMod(SpellValueMod.BasePoint1, damageForAuraRemoveAmount); + caster.CastSpell(target, SpellIds.ShadowMendPeriodicDummy, args); } } - - public override void Register() - { - CalcDamage.Add(new(HandleDamageCalculation)); - - // abuse OnCalculateResistAbsorb to determine if this spell will kill target or not (its still not perfect - happens before absorbs are applied) - OnCalculateResistAbsorb.Add(new(DetermineKillStatus)); - } } - [Script] // 109186 - Surge of Light - class spell_pri_surge_of_light : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Smite, SpellIds.SurgeOfLightEffect); - } + AfterHit.Add(new(HandleEffectHit)); + } +} - bool CheckProc(ProcEventInfo eventInfo) - { - if (eventInfo.GetSpellInfo().Id == SpellIds.Smite) - return true; - - if (eventInfo.GetSpellInfo().SpellFamilyName == SpellFamilyNames.Priest) - return eventInfo.GetHealInfo() != null; - - return false; - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - if (RandomHelper.randChance(aurEff.GetAmount())) - GetTarget().CastSpell(GetTarget(), SpellIds.SurgeOfLightEffect, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } +[Script] // 187464 - Shadow Mend (Damage) +class spell_pri_shadow_mend_periodic_damage : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowMendDamage); } - [Script] // 28809 - Greater Heal - class spell_pri_t3_4p_bonus : AuraScript + void HandleDummyTick(AuraEffect aurEff) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ArmorOfFaith); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.ArmorOfFaith, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.SetOriginalCaster(GetCasterGUID()); + args.SetTriggeringAura(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount()); + GetTarget().CastSpell(GetTarget(), SpellIds.ShadowMendDamage, args); } - [Script] // 37594 - Greater Heal Refund - class spell_pri_t5_heal_2p_bonus : AuraScript + static bool CheckProc(ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ItemEfficiency); - } + return eventInfo.GetDamageInfo() != null; + } - bool CheckProc(ProcEventInfo eventInfo) + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + int newAmount = aurEff.GetAmount() - (int)eventInfo.GetDamageInfo().GetDamage(); + + aurEff.ChangeAmount(newAmount); + if (newAmount < 0) + Remove(); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy)); + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 32379 - Shadow Word: Death +class spell_pri_shadow_word_death : SpellScript +{ + static TimeSpan BacklashDelay = TimeSpan.FromSeconds(1); + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowWordDeathDamage) + && ValidateSpellEffect((spellInfo.Id, 5)) + && spellInfo.GetEffect(2).IsEffect(SpellEffectName.Dummy) + && spellInfo.GetEffect(3).IsEffect(SpellEffectName.ScriptEffect) + && spellInfo.GetEffect(5).IsEffect(SpellEffectName.Dummy); + } + + void HandleDamageCalculation(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + if (victim.HealthBelowPct(GetEffectInfo(2).CalcValue(GetCaster()))) + MathFunctions.AddPct(ref pctMod, GetEffectInfo(3).CalcValue(GetCaster())); + } + + void DetermineKillStatus(DamageInfo damageInfo, ref uint resistAmount, ref int absorbAmount) + { + bool killed = damageInfo.GetDamage() >= damageInfo.GetVictim().GetHealth(); + if (!killed) { - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo != null) + Unit caster = GetCaster(); + int backlashDamage = (int)caster.CountPctFromMaxHealth(GetEffectInfo(5).CalcValue(caster)); + var originalCastId = GetSpell().m_castId; + caster.m_Events.AddEventAtOffset(() => { - Unit healTarget = healInfo.GetTarget(); - if (healTarget != null && healInfo.GetEffectiveHeal() != 0) - if (healTarget.GetHealth() >= healTarget.GetMaxHealth()) - return true; - } + caster.CastSpell(caster, SpellIds.ShadowWordDeathDamage, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetOriginalCastId(originalCastId) + .AddSpellMod(SpellValueMod.BasePoint0, backlashDamage)); - return false; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellIds.ItemEfficiency, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + }, BacklashDelay); } } - [Script] // 70770 - Item - Priest T10 Healer 2P Bonus - class spell_pri_t10_heal_2p_bonus : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlessedHealing); - } + CalcDamage.Add(new(HandleDamageCalculation)); - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); + // abuse OnCalculateResistAbsorb to determine if this spell will kill target or not (its still not perfect - happens before absorbs are applied) + OnCalculateResistAbsorb.Add(new(DetermineKillStatus)); + } +} - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo == null || healInfo.GetHeal() == 0) - return; - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.BlessedHealing, GetCastDifficulty()); - int amount = MathFunctions.CalculatePct((int)(healInfo.GetHeal()), aurEff.GetAmount()); - - Cypher.Assert(spellInfo.GetMaxTicks() > 0); - amount /= (int)spellInfo.GetMaxTicks(); - - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(target, SpellIds.BlessedHealing, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 109186 - Surge of Light +class spell_pri_surge_of_light : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Smite, SpellIds.SurgeOfLightEffect); } - [Script] // 200128 - Trail of Light - class spell_pri_trail_of_light : AuraScript + static bool CheckProc(ProcEventInfo eventInfo) { - Queue _healQueue = new(); + if (eventInfo.GetSpellInfo().Id == SpellIds.Smite) + return true; - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.TrailOfLightHeal); - } + if (eventInfo.GetSpellInfo().SpellFamilyName == SpellFamilyNames.Priest) + return eventInfo.GetHealInfo() != null; - bool CheckProc(ProcEventInfo eventInfo) - { - if (_healQueue.Count == 0 || _healQueue.Last() != eventInfo.GetActionTarget().GetGUID()) - _healQueue.Enqueue(eventInfo.GetActionTarget().GetGUID()); - - if (_healQueue.Count > 2) - _healQueue.Dequeue(); - - if (_healQueue.Count == 2) - return true; - - return false; - } - - void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = GetTarget(); - Unit oldTarget = ObjAccessor.GetUnit(caster, _healQueue.First()); - if (oldTarget == null) - return; - - // Note: old target may not be friendly anymore due to charm and faction change effects. - if (!caster.IsValidAssistTarget(oldTarget)) - return; - - SpellInfo healSpellInfo = SpellMgr.GetSpellInfo(SpellIds.TrailOfLightHeal, Difficulty.None); - if (healSpellInfo == null) - return; - - // Note: distance may be greater than the heal's spell range. - if (!caster.IsWithinDist(oldTarget, healSpellInfo.GetMaxRange(true, caster))) - return; - - uint healAmount = MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), aurEff.GetAmount()); - - caster.CastSpell(oldTarget, SpellIds.TrailOfLightHeal, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, (int)healAmount)); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); - } + return false; } - // 390693 - Train of Thought - [Script] // Called by Flash Heal, Renew, Smite - class spell_pri_train_of_thought : AuraScript + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PowerWordShield, SpellIds.Penance); - } - - bool CheckEffect0(AuraEffect aurEff, ProcEventInfo eventInfo) - { - // Renew & Flash Heal - return eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Priest, new FlagArray128(0x840)); - } - - bool CheckEffect1(AuraEffect aurEff, ProcEventInfo eventInfo) - { - // Smite - return eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Priest, new FlagArray128(0x80)); - } - - void ReducePowerWordShieldCooldown(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.PowerWordShield, TimeSpan.FromMilliseconds(aurEff.GetAmount())); - } - - void ReducePenanceCooldown(AuraEffect aurEff, ProcEventInfo eventInfo) - { - GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.Penance, TimeSpan.FromMilliseconds(aurEff.GetAmount())); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckEffect0, 0, AuraType.Dummy)); - OnEffectProc.Add(new(ReducePowerWordShieldCooldown, 0, AuraType.Dummy)); - DoCheckEffectProc.Add(new(CheckEffect1, 1, AuraType.Dummy)); - OnEffectProc.Add(new(ReducePenanceCooldown, 1, AuraType.Dummy)); - } + if (RandomHelper.randChance(aurEff.GetAmount())) + GetTarget().CastSpell(GetTarget(), SpellIds.SurgeOfLightEffect, aurEff); } - // 109142 - Twist of Fate (Shadow) - [Script] // 265259 - Twist of Fate (Discipline) - class spell_pri_twist_of_fate : AuraScript + public override void Register() { - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcTarget().GetHealthPct() < aurEff.GetAmount(); - } + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } +[Script] // 28809 - Greater Heal +class spell_pri_t3_4p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ArmorOfFaith); } - // 341273 - Unfurling Darkness - [Script] // Triggered by 34914 - Vampiric Touch - class spell_pri_unfurling_darkness : SpellScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.UnfurlingDarkness, SpellIds.UnfurlingDarknessDebuff) - && ValidateSpellEffect((SpellIds.UnfurlingDarknessAura, 0)); - } + PreventDefaultAction(); + eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.ArmorOfFaith, aurEff); + } - void PreventDirectDamage(ref WorldObject target) + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 37594 - Greater Heal Refund +class spell_pri_t5_heal_2p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ItemEfficiency); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo != null) { - bool canTriggerDirectDamage = new Func(() => - { - if (!GetSpell().m_originalCastId.IsEmpty()) - return false; // not when triggered by Shadow Crash (Whispering Shadows talent) - AuraEffect unfurlingDarkness = GetCaster().GetAuraEffect(SpellIds.UnfurlingDarknessAura, 0); - if (unfurlingDarkness != null && GetSpell().m_appliedMods.Contains(unfurlingDarkness.GetBase())) + Unit healTarget = healInfo.GetTarget(); + if (healTarget != null && healInfo.GetEffectiveHeal() != 0) + if (healTarget.GetHealth() >= healTarget.GetMaxHealth()) return true; - return false; - })(); - - if (!canTriggerDirectDamage) - target = null; } - void TriggerUnfurlingDarkness() + return false; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.ItemEfficiency, aurEff); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 70770 - Item - Priest T10 Healer 2P Bonus +class spell_pri_t10_heal_2p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlessedHealing); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo == null || healInfo.GetHeal() == 0) + return; + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.BlessedHealing, GetCastDifficulty()); + int amount = MathFunctions.CalculatePct((int)(healInfo.GetHeal()), aurEff.GetAmount()); + + Cypher.Assert(spellInfo.GetMaxTicks() > 0); + amount /= (int)spellInfo.GetMaxTicks(); + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, amount); + caster.CastSpell(target, SpellIds.BlessedHealing, args); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 200128 - Trail of Light +class spell_pri_trail_of_light : AuraScript +{ + Queue _healQueue = new(); + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TrailOfLightHeal); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (_healQueue.Count == 0 || _healQueue.Last() != eventInfo.GetActionTarget().GetGUID()) + _healQueue.Enqueue(eventInfo.GetActionTarget().GetGUID()); + + if (_healQueue.Count > 2) + _healQueue.Dequeue(); + + if (_healQueue.Count == 2) + return true; + + return false; + } + + void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = GetTarget(); + Unit oldTarget = Global.ObjAccessor.GetUnit(caster, _healQueue.Peek()); + if (oldTarget == null) + return; + + // Note: old target may not be friendly anymore due to charm and faction change effects. + if (!caster.IsValidAssistTarget(oldTarget)) + return; + + SpellInfo healSpellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.TrailOfLightHeal, Difficulty.None); + if (healSpellInfo == null) + return; + + // Note: distance may be greater than the heal's spell range. + if (!caster.IsWithinDist(oldTarget, healSpellInfo.GetMaxRange(true, caster))) + return; + + uint healAmount = MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), aurEff.GetAmount()); + + caster.CastSpell(oldTarget, SpellIds.TrailOfLightHeal, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, (int)healAmount)); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy)); + } +} + +// 390693 - Train of Thought +[Script] // Called by Flash Heal, Renew, Smite +class spell_pri_train_of_thought : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerWordShield, SpellIds.Penance); + } + + static bool CheckEffect0(AuraEffect aurEff, ProcEventInfo eventInfo) + { + // Renew & Flash Heal + return eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Priest, new FlagArray128(0x840)); + } + + static bool Check1(AuraEffect aurEff, ProcEventInfo eventInfo) + { + // Smite + return eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Priest, new FlagArray128(0x80)); + } + + void ReducePowerWordShieldCooldown(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.PowerWordShield, TimeSpan.FromSeconds(aurEff.GetAmount())); + } + + void ReducePenanceCooldown(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.Penance, TimeSpan.FromSeconds(aurEff.GetAmount())); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckEffect0, 0, AuraType.Dummy)); + OnEffectProc.Add(new(ReducePowerWordShieldCooldown, 0, AuraType.Dummy)); + DoCheckEffectProc.Add(new(Check1, 1, AuraType.Dummy)); + OnEffectProc.Add(new(ReducePenanceCooldown, 1, AuraType.Dummy)); + } +} + +// 109142 - Twist of Fate (Shadow) +[Script] // 265259 - Twist of Fate (Discipline) +class spell_pri_twist_of_fate : AuraScript +{ + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcTarget().GetHealthPct() < aurEff.GetAmount(); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +// 341273 - Unfurling Darkness +[Script] // Triggered by 34914 - Vampiric Touch +class spell_pri_unfurling_darkness : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UnfurlingDarkness, SpellIds.UnfurlingDarknessDebuff) + && ValidateSpellEffect((SpellIds.UnfurlingDarknessAura, 0)); + } + + void PreventDirectDamage(ref WorldObject target) + { + bool canTriggerDirectDamage() { if (!GetSpell().m_originalCastId.IsEmpty()) - return; // not when triggered by Shadow Crash (Whispering Shadows talent) - - Unit caster = GetCaster(); + return false; // not when triggered by Shadow Crash (Whispering Shadows talent) AuraEffect unfurlingDarkness = GetCaster().GetAuraEffect(SpellIds.UnfurlingDarknessAura, 0); if (unfurlingDarkness != null) - { if (GetSpell().m_appliedMods.Contains(unfurlingDarkness.GetBase())) - { - unfurlingDarkness.GetBase().Remove(); - return; - } - } - - if (!caster.HasAura(SpellIds.UnfurlingDarknessDebuff)) - caster.CastSpell(caster, SpellIds.UnfurlingDarknessAura, true); + return true; + return false; } + ; - public override void Register() - { - OnObjectTargetSelect.Add(new ObjectTargetSelectHandler(PreventDirectDamage, 3, Targets.UnitTargetEnemy)); - AfterCast.Add(new CastHandler(TriggerUnfurlingDarkness)); - } + if (!canTriggerDirectDamage()) + target = null; } - [Script] // 15286 - Vampiric Embrace - class spell_pri_vampiric_embrace : AuraScript + void TriggerUnfurlingDarkness() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.VampiricEmbraceHeal); - } + if (!GetSpell().m_originalCastId.IsEmpty()) + return; // not when triggered by Shadow Crash (Whispering Shadows talent) - bool CheckProc(ProcEventInfo eventInfo) - { - // Not proc from Mind Sear - return (eventInfo.GetDamageInfo().GetSpellInfo().SpellFamilyFlags[1] & 0x80000) == 0; - } + Unit caster = GetCaster(); - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + AuraEffect unfurlingDarkness = GetCaster().GetAuraEffect(SpellIds.UnfurlingDarknessAura, 0); + if (unfurlingDarkness != null) { - PreventDefaultAction(); - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) + if (GetSpell().m_appliedMods.Contains(unfurlingDarkness.GetBase())) + { + unfurlingDarkness.GetBase().Remove(); return; - - int selfHeal = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount()); - int teamHeal = selfHeal / 2; - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, teamHeal); - args.AddSpellMod(SpellValueMod.BasePoint1, selfHeal); - GetTarget().CastSpell(null, SpellIds.VampiricEmbraceHeal, args); + } } - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } + if (!caster.HasAura(SpellIds.UnfurlingDarknessDebuff)) + caster.CastSpell(caster, SpellIds.UnfurlingDarknessAura, true); } - [Script] // 15290 - Vampiric Embrace (heal) - class spell_pri_vampiric_embrace_target : SpellScript + public override void Register() { - void FilterTargets(List unitList) - { - unitList.Remove(GetCaster()); - } + OnObjectTargetSelect.Add(new(PreventDirectDamage, 3, Targets.UnitTargetEnemy)); + AfterCast.Add(new(TriggerUnfurlingDarkness)); + } +} - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitCasterAreaParty)); - } +[Script] // 15286 - Vampiric Embrace +class spell_pri_vampiric_embrace : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VampiricEmbraceHeal); } - [Script] // 34914 - Vampiric Touch - class spell_pri_vampiric_touch : AuraScript + static bool CheckProc(ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SinAndPunishment, SpellIds.ShadowWordPain); - } + // Not proc from Mind Sear + return (eventInfo.GetDamageInfo().GetSpellInfo().SpellFamilyFlags[1] & 0x80000) == 0; + } - void HandleDispel(DispelInfo dispelInfo) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(dispelInfo.GetDispeller(), SpellIds.SinAndPunishment, true); - } + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; - void HandleApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null && caster.HasAura(SpellIds.Misery)) + int selfHeal = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount()); + int teamHeal = selfHeal / 2; + + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, teamHeal); + args.AddSpellMod(SpellValueMod.BasePoint1, selfHeal); + GetTarget().CastSpell(null, SpellIds.VampiricEmbraceHeal, args); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 15290 - Vampiric Embrace (heal) +class spell_pri_vampiric_embrace_target : SpellScript +{ + void FilterTargets(List unitList) + { + unitList.Remove(GetCaster()); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitCasterAreaParty)); + } +} + +[Script] // 34914 - Vampiric Touch +class spell_pri_vampiric_touch : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SinAndPunishment, SpellIds.ShadowWordPain); + } + + void HandleDispel(DispelInfo dispelInfo) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(dispelInfo.GetDispeller(), SpellIds.SinAndPunishment, true); + } + + void HandleApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + if (caster.HasAura(SpellIds.Misery)) caster.CastSpell(GetTarget(), SpellIds.ShadowWordPain, true); - } - - public override void Register() - { - AfterDispel.Add(new(HandleDispel)); - OnEffectApply.Add(new(HandleApplyEffect, 0, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); - } } - [Script] // 205385 - Shadow Crash - class spell_pri_whispering_shadows : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.WhisperingShadows); - } - - void HandleEffectHitTarget(uint effIndex) - { - if (!GetCaster().HasAura(SpellIds.WhisperingShadows)) - PreventHitDefaultEffect(effIndex); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffectHitTarget, 2, SpellEffectName.TriggerMissile)); - } + AfterDispel.Add(new(HandleDispel)); + OnEffectApply.Add(new(HandleApplyEffect, 0, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask)); } +} - [Script] // 391286 - Whispering Shadows (Dot Application) - class spell_pri_whispering_shadows_effect : SpellScript +[Script] // 205385 - Shadow Crash +class spell_pri_whispering_shadows : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.VampiricTouch); - } - - void FilterTargets(List targets) - { - if (targets.Count <= GetSpellValue().MaxAffectedTargets) - return; - - Aura getVampiricTouch(WorldObject target) - { - return target.ToUnit().GetAura(SpellIds.VampiricTouch, GetCaster().GetGUID()); - } - - // prioritize targets without Vampiric Touch - targets.Sort((WorldObject target1, WorldObject target2) => - { - int duration1 = 0; - Aura aura1 = getVampiricTouch(target1); - if (aura1 != null) - duration1 = aura1.GetDuration(); - int duration2 = 0; - Aura aura2 = getVampiricTouch(target2); - if (aura2 != null) - duration2 = aura2.GetDuration(); - return duration1.CompareTo(duration2); - }); - - // remove targets that definitely will not get Vampiric Touch applied (excess targets with longest remaining duration) - while (targets.Count > GetSpellValue().MaxAffectedTargets && getVampiricTouch(targets.Last()) != null) - targets.RemoveAt(targets.Count - 1); - - targets.RandomResize(GetSpellValue().MaxAffectedTargets); - } - - void HandleEffectHitTarget(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.VampiricTouch, new CastSpellExtraArgs() - .SetTriggeringSpell(GetSpell()) - .SetTriggerFlags(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.IgnoreCastTime | TriggerCastFlags.DontReportCastError)); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); - } + return ValidateSpellInfo(SpellIds.WhisperingShadows); } -} \ No newline at end of file + + void HandleEffectHitTarget(uint effIndex) + { + if (!GetCaster().HasAura(SpellIds.WhisperingShadows)) + PreventHitDefaultEffect(effIndex); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEffectHitTarget, 2, SpellEffectName.TriggerMissile)); + } +} + +[Script] // 391286 - Whispering Shadows (Dot Application) +class spell_pri_whispering_shadows_effect : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VampiricTouch); + } + + void FilterTargets(List targets) + { + if (targets.Count <= GetSpellValue().MaxAffectedTargets) + return; + + Aura getVampiricTouch(WorldObject target) + { + return target.ToUnit().GetAura(SpellIds.VampiricTouch, GetCaster().GetGUID()); + } + + // prioritize targets without Vampiric Touch + targets.Sort((target1, target2) => + { + int duration1 = 0; + Aura aura1 = getVampiricTouch(target1); + if (aura1 != null) + duration1 = aura1.GetDuration(); + int duration2 = 0; + Aura aura2 = getVampiricTouch(target2); + if (aura2 != null) + duration2 = aura2.GetDuration(); + return duration1.CompareTo(duration2); + }); + + // remove targets that definitely will not get Vampiric Touch applied (excess targets with longest remaining duration) + while (targets.Count > GetSpellValue().MaxAffectedTargets && getVampiricTouch(targets.Last()) != null) + targets.RemoveAt(targets.Count - 1); + + targets.RandomResize(GetSpellValue().MaxAffectedTargets); + } + + void HandleEffectHitTarget(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.VampiricTouch, new CastSpellExtraArgs() + .SetTriggeringSpell(GetSpell()) + .SetTriggerFlags(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.IgnoreCastTime | TriggerCastFlags.DontReportCastError)); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); + } +} + diff --git a/Source/Scripts/Spells/Quest.cs b/Source/Scripts/Spells/Quest.cs index ba30682b9..1e6b85cb2 100644 --- a/Source/Scripts/Spells/Quest.cs +++ b/Source/Scripts/Spells/Quest.cs @@ -1,1755 +1,1791 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; +using Framework.Dynamic; +using Game.AI; using Game.Entities; -using Game.Maps; +using Game.Movement; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using static Global; +using System.Linq; -namespace Scripts.Spells.Azerite +namespace Scripts.Spells.Quest; + +struct SpellIds { - struct GenericQuestUpdateEntryIds + // ThaumaturgyChannel + public const uint ThaumaturgyChannel = 21029; + + // Quest11396_11399Data + public const uint ForceShieldArcanePurpleX3 = 43874; + public const uint ScourgingCrystalController = 43878; + + // Quest11730Data + public const uint SummonScavengebot004A8 = 46063; + public const uint SummonSentrybot57K = 46068; + public const uint SummonDefendotank66D = 46058; + public const uint SummonScavengebot005B6 = 46066; + public const uint Summon55DCollectatron = 46034; + public const uint RobotKillCredit = 46027; + + // Quest12634Data + public const uint BananasFallToGround = 51836; + public const uint OrangeFallsToGround = 51837; + public const uint PapayaFallsToGround = 51839; + public const uint SummonAdventurousDwarf = 52070; + + // Quest12851Data + public const uint FrostgiantCredit = 58184; + public const uint FrostworgCredit = 58183; + public const uint Immolation = 54690; + public const uint Ablaze = 54683; + + // BattleStandard + public const uint PlantHordeBattleStandard = 59643; + public const uint HordeBattleStandardState = 59642; + public const uint AllianceBattleStandardState = 4339; + public const uint JumpRocketBlast = 4340; + + // FocusOnTheBeach + public const uint BunnyCreditBeam = 47390; + + // DefendingWyrmrestTemple + public const uint SummonWyrmrestDefender = 49207; + + // Quest11010_11102_11023Data + public const uint FlakCannonTrigger = 40110; + public const uint ChooseLoc = 40056; + public const uint AggroCheck = 40112; + + // SpellZuldrakRat + public const uint SummonGorgedLurkingBasilisk = 50928; + + // QuenchingMist + public const uint FlickeringFlames = 53504; + + // Quest13291_13292_13239_13261Data + public const uint Ride = 59319; + + // BurstAtTheSeams + public const uint BloatedAbominationFeignDeath = 52593; + public const uint BurstAtTheSeamsBone = 52516; + public const uint ExplodeAbominationMeat = 52520; + public const uint ExplodeAbominationBloodyMeat = 52523; + public const uint TrollExplosion = 52565; + public const uint ExplodeTrollMeat = 52578; + public const uint ExplodeTrollBloodyMeat = 52580; + public const uint BurstAtTheSeams59576 = 59576; //script/knockback; That's Abominable + public const uint BurstAtTheSeams59579 = 59579; //dummy + public const uint BurstAtTheSeams52510 = 52510; //script/knockback; Fuel for the Fire + public const uint BurstAtTheSeams52508 = 52508; //damage 20000 + public const uint BurstAtTheSeams59580 = 59580; //damage 50000 + public const uint AssignGhoulKillCreditToMaster = 59590; + public const uint AssignGeistKillCreditToMaster = 60041; + public const uint AssignSkeletonKillCreditToMaster = 60039; + public const uint DrakkariSkullcrusherCredit = 52590; + public const uint SummonDrakkariChieftain = 52616; + public const uint DrakkariChieftainkKillCredit = 52620; + + // EscapeFromSilverbrook + public const uint SummonWorgen = 48681; + + // DeathComesFromOnHigh + public const uint ForgeCredit = 51974; + public const uint TownHallCredit = 51977; + public const uint ScarletHoldCredit = 51980; + public const uint ChapelCredit = 51982; + + // QuestTheStormKing + public const uint RideGymer = 43671; + public const uint Grabbed = 55424; + + // QuestTheStormKingThrow + public const uint VargulExplosion = 55569; + + // QuestTheHunterAndThePrince + public const uint IllidanKillCredit = 61748; + + // RelicOfTheEarthenRing + public const uint TotemOfTheEarthenRing = 66747; + + // Fumping + public const uint SummonSandGnome = 39240; + public const uint SummonBoneSlicer = 39241; + + // FearNoEvil + public const uint RenewedLife = 93097; + + // ApplyHeatAndStir + public const uint SpurtsAndSmoke = 38594; + public const uint ErrorMix1 = 43376; + public const uint ErrorMix2 = 43378; + public const uint ErrorMix3 = 43970; + public const uint SuccessfulMix = 43377; + + // TamingTheBeast + public const uint TameIceClawBear = 19548; + public const uint TameLargeCragBoar = 19674; + public const uint TameSnowLeopard = 19687; + public const uint TameAdultPlainstrider = 19688; + public const uint TamePrairieStalker = 19689; + public const uint TameSwoop = 19692; + public const uint TameWebwoodLurker = 19693; + public const uint TameDireMottledBoar = 19694; + public const uint TameSurfCrawler = 19696; + public const uint TameArmoredScorpid = 19697; + public const uint TameNightsaberStalker = 19699; + public const uint TameStrigidScreecher = 19700; + public const uint TameBarbedCrawler = 30646; + public const uint TameGreaterTimberstrider = 30653; + public const uint TameNightstalker = 30654; + public const uint TameCrazedDragonhawk = 30099; + public const uint TameElderSpringpaw = 30102; + public const uint TameMistbat = 30105; + public const uint TameIceClawBear1 = 19597; + public const uint TameLargeCragBoar1 = 19677; + public const uint TameSnowLeopard1 = 19676; + public const uint TameAdultPlainstrider1 = 19678; + public const uint TamePrairieStalker1 = 19679; + public const uint TameSwoop1 = 19680; + public const uint TameWebwoodLurker1 = 19684; + public const uint TameDireMottledBoar1 = 19681; + public const uint TameSurfCrawler1 = 19682; + public const uint TameArmoredScorpid1 = 19683; + public const uint TameNightsaberStalker1 = 19685; + public const uint TameStrigidScreecher1 = 19686; + public const uint TameBarbedCrawler1 = 30647; + public const uint TameGreaterTimberstrider1 = 30648; + public const uint TameNightstalker1 = 30652; + public const uint TameCrazedDragonhawk1 = 30100; + public const uint TameElderSpringpaw1 = 30103; + public const uint TameMistbat1 = 30104; + + // TributeSpells + public const uint GromsTrollTribute = 24101; + public const uint GromsTaurenTribute = 24102; + public const uint GromsUndeadTribute = 24103; + public const uint GromsOrcTribute = 24104; + public const uint GromsBloodelfTribute = 69530; + public const uint UthersHumanTribute = 24105; + public const uint UthersGnomeTribute = 24106; + public const uint UthersDwarfTribute = 24107; + public const uint UthersNightelfTribute = 24108; + public const uint UthersDraeneiTribute = 69533; +} + +struct CreatureIds +{ + // Quest55Data + public const uint Morbent = 1200; + public const uint WeakenedMorbent = 24782; + + // Quests6124_6129Data + public const uint SicklyGazelle = 12296; + public const uint CuredGazelle = 12297; + public const uint SicklyDeer = 12298; + public const uint CuredDeer = 12299; + + // Quest10255Data + public const uint Helboar = 16880; + public const uint Dreadtusk = 16992; + + // Quest11515Data + public const uint FelbloodInitiate = 24918; + public const uint EmaciatedFelblood = 24955; + + // Quest11730Data + public const uint Scavengebot004A8 = 25752; + public const uint Sentrybot57K = 25753; + public const uint Defendotank66D = 25758; + public const uint Scavengebot005B6 = 25792; + public const uint Collectatron55D = 25793; + + // Quest12459Data + public const uint ReanimatedFrostwyrm = 26841; + public const uint WeakReanimatedFrostwyrm = 27821; + public const uint Turgid = 27808; + public const uint WeakTurgid = 27809; + public const uint Deathgaze = 27122; + public const uint WeakDeathgaze = 27807; + + // Quest12851Data + public const uint Frostgiant = 29351; + public const uint Frostworg = 29358; + + // Quest12659Data + public const uint ScalpsKcBunny = 28622; + + // SalvagingLifesStength + public const uint ShardKillCredit = 29303; + + // BattleStandard + public const uint KingOfTheMountaintKc = 31766; + + // Quest12372Data + public const uint WyrmrestTempleCredit = 27698; + + // Quest11010_11102_11023Data + public const uint FelCannon2 = 23082; + + // Quest13291_13292_13239_13261Data + public const uint Skytalon = 31583; + public const uint Decoy = 31578; + + // BurstAtTheSeams + public const uint DrakkariChieftaink = 29099; + public const uint IcyGhoul = 31142; + public const uint ViciousGeist = 31147; + public const uint RisenAllianceSoldiers = 31205; + public const uint RenimatedAbomination = 31692; + + // DeathComesFromOnHigh + public const uint NewAvalonForge = 28525; + public const uint NewAvalonTownHall = 28543; + public const uint ScarletHold = 28542; + public const uint ChapelOfTheCrimsonFlame = 28544; + + // FearNoEvil + public const uint InjuredStormwindInfantry = 50047; + + // CallAttackMastiffs + public const uint AttackMastiff = 36405; +} + +struct MiscConst +{ + // BurstAtTheSeams + public const uint AreaTheBrokenFront = 4507; + public const uint AreaMordRetharTheDeathGate = 4508; + public const uint QuestFuelForTheFire = 12690; + + // Recall_Eye_of_Acherus + public const uint TheEyeOfAcherus = 51852; + + // ApplyHeatAndStir + public const uint CreatureGenericTriggerLab = 24042; + public const uint Talk0 = 0; + public const uint Talk1 = 1; +} + +[Script("spell_q55_sacred_cleansing", SpellEffectName.Dummy, 1, CreatureIds.Morbent, CreatureIds.WeakenedMorbent, true)] // 8913 - Sacred Cleansing +[Script("spell_q10255_administer_antidote", SpellEffectName.Dummy, 0, CreatureIds.Helboar, CreatureIds.Dreadtusk, true)] // 34665 - Administer Antidote +[Script("spell_q11515_fel_siphon_dummy", SpellEffectName.Dummy, 0, CreatureIds.FelbloodInitiate, CreatureIds.EmaciatedFelblood, true)] // 44936 - Quest - Fel Siphon Dummy +class spell_generic_quest_update_entry : SpellScript +{ + SpellEffectName _spellEffect; + uint _effIndex; + uint _originalEntry; + uint _newEntry; + bool _shouldAttack; + TimeSpan _despawnTime; + + public spell_generic_quest_update_entry(SpellEffectName spellEffect, uint effIndex, uint originalEntry, uint newEntry, bool shouldAttack, TimeSpan despawnTime) { - // http://www.wowhead.com/quest=55 Morbent Fel - public const uint Morbent = 1200; - public const uint WeakenedMorbent = 24782; - - // http://www.wowhead.com/quest=10255 Testing the Antidote - public const uint Helboar = 16880; - public const uint Dreadtusk = 16992; - - // http://www.wowhead.com/quest=11515 Blood for Blood - public const uint FelbloodInitiate = 24918; - public const uint EmaciatedFelblood = 24955; + _spellEffect = spellEffect; + _effIndex = effIndex; + _originalEntry = originalEntry; + _newEntry = newEntry; + _shouldAttack = shouldAttack; + _despawnTime = despawnTime; } - [Script("spell_q55_sacred_cleansing", SpellEffectName.Dummy, 1u, GenericQuestUpdateEntryIds.Morbent, GenericQuestUpdateEntryIds.WeakenedMorbent, true)] // 8913 - Sacred Cleansing - [Script("spell_q10255_administer_antidote", SpellEffectName.Dummy, 0u, GenericQuestUpdateEntryIds.Helboar, GenericQuestUpdateEntryIds.Dreadtusk, true)] // 34665 - Administer Antidote - [Script("spell_q11515_fel_siphon_dummy", SpellEffectName.Dummy, 0u, GenericQuestUpdateEntryIds.FelbloodInitiate, GenericQuestUpdateEntryIds.EmaciatedFelblood, true)] // 44936 - Quest - Fel Siphon Dummy - class spell_generic_quest_update_entry : SpellScript + public spell_generic_quest_update_entry(SpellEffectName spellEffect, uint effIndex, uint originalEntry, uint newEntry, bool shouldAttack) { - SpellEffectName _spellEffect; - byte _effIndex; - uint _originalEntry; - uint _newEntry; - bool _shouldAttack; + _spellEffect = spellEffect; + _effIndex = effIndex; + _originalEntry = originalEntry; + _newEntry = newEntry; + _shouldAttack = shouldAttack; + _despawnTime = TimeSpan.Zero; + } - public spell_generic_quest_update_entry(SpellEffectName spellEffect, uint effIndex, uint originalEntry, uint newEntry, bool shouldAttack) + void HandleDummy(uint effIndex) + { + Creature creatureTarget = GetHitCreature(); + if (creatureTarget != null && !creatureTarget.IsPet() && creatureTarget.GetEntry() == _originalEntry) { - _spellEffect = spellEffect; - _effIndex = (byte)effIndex; - _originalEntry = originalEntry; - _newEntry = newEntry; - _shouldAttack = shouldAttack; - } + creatureTarget.UpdateEntry(_newEntry); + if (_shouldAttack) + creatureTarget.EngageWithTarget(GetCaster()); - void HandleDummy(uint effIndex) + if (_despawnTime != TimeSpan.FromSeconds(0)) + creatureTarget.DespawnOrUnsummon(_despawnTime); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, _effIndex, _spellEffect)); + } +} + +[Script] // 9712 - Thaumaturgy Channel +class spell_q2203_thaumaturgy_channel : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ThaumaturgyChannel); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + PreventDefaultAction(); + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.ThaumaturgyChannel, false); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 19512 - Apply Salve +class spell_q6124_6129_apply_salve : SpellScript +{ + TimeSpan despawnTime = TimeSpan.FromSeconds(30); + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleDummy(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + if (GetCastItem() != null) { Creature creatureTarget = GetHitCreature(); if (creatureTarget != null) { - if (creatureTarget.IsPet() && creatureTarget.GetEntry() == _originalEntry) + uint newEntry = 0; + switch (caster.GetTeam()) { - creatureTarget.UpdateEntry(_newEntry); - if (_shouldAttack) - creatureTarget.EngageWithTarget(GetCaster()); + case Team.Horde: + if (creatureTarget.GetEntry() == CreatureIds.SicklyGazelle) + newEntry = CreatureIds.CuredGazelle; + break; + case Team.Alliance: + if (creatureTarget.GetEntry() == CreatureIds.SicklyDeer) + newEntry = CreatureIds.CuredDeer; + break; + default: + break; + } + if (newEntry != 0) + { + creatureTarget.UpdateEntry(newEntry); + creatureTarget.DespawnOrUnsummon(despawnTime); + caster.KilledMonsterCredit(newEntry); } } } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, _effIndex, _spellEffect)); - } } - [Script] // 9712 - Thaumaturgy Channel - class spell_q2203_thaumaturgy_channel : AuraScript + public override void Register() { - const uint SpellThaumaturgyChannel = 21029; + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellThaumaturgyChannel); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - PreventDefaultAction(); - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, SpellThaumaturgyChannel, false); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); - } +[Script] // 43874 - Scourge Mur'gul Camp: Force Shield Arcane Purple x3 +class spell_q11396_11399_force_shield_arcane_purple_x3 : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetImmuneToPC(true); + target.AddUnitState(UnitState.Root); } - [Script] // 19512 - Apply Salve - class spell_q6124_6129_apply_salve : SpellScript + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - const uint NpcSicklyGazelle = 12296; - const uint NpcCuredGazelle = 12297; - const uint NpcSicklyDeer = 12298; - const uint NpcCuredDeer = 12299; + GetTarget().SetImmuneToPC(false); + } - TimeSpan Quest6124_6129_DESPAWN_TIME = TimeSpan.FromSeconds(30); + public override void Register() + { + OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - public override bool Load() +[Script] // 50133 - Scourging Crystal Controller +class spell_q11396_11399_scourging_crystal_controller : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ForceShieldArcanePurpleX3, SpellIds.ScourgingCrystalController); + } + + void HandleDummy(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) + if (target.IsUnit() && target.HasAura(SpellIds.ForceShieldArcanePurpleX3)) + // Make sure nobody else is channeling the same target + if (!target.HasAura(SpellIds.ScourgingCrystalController)) + GetCaster().CastSpell(target, SpellIds.ScourgingCrystalController, GetCastItem()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 43882 - Scourging Crystal Controller Dummy +class spell_q11396_11399_scourging_crystal_controller_dummy : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ForceShieldArcanePurpleX3); + } + + void HandleDummy(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) + if (target.IsUnit()) + target.RemoveAurasDueToSpell(SpellIds.ForceShieldArcanePurpleX3); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 46023 - The Ultrasonic Screwdriver +class spell_q11730_ultrasonic_screwdriver : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer() && GetCastItem() != null; + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SummonScavengebot004A8, SpellIds.SummonSentrybot57K, SpellIds.SummonDefendotank66D, SpellIds.SummonScavengebot005B6, SpellIds.Summon55DCollectatron, SpellIds.RobotKillCredit); + } + + void HandleDummy(uint effIndex) + { + Item castItem = GetCastItem(); + Unit caster = GetCaster(); + Creature target = GetHitCreature(); + if (target != null) { - return GetCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - if (GetCastItem() != null) + uint spellId = 0; + switch (target.GetEntry()) { - Creature creatureTarget = GetHitCreature(); - if (creatureTarget != null) - { - uint newEntry = 0; - switch (caster.GetTeam()) - { - case Team.Horde: - if (creatureTarget.GetEntry() == NpcSicklyGazelle) - newEntry = NpcCuredGazelle; - break; - case Team.Alliance: - if (creatureTarget.GetEntry() == NpcSicklyDeer) - newEntry = NpcCuredDeer; - break; - } - if (newEntry != 0) - { - creatureTarget.UpdateEntry(newEntry); - creatureTarget.DespawnOrUnsummon(Quest6124_6129_DESPAWN_TIME); - caster.KilledMonsterCredit(newEntry); - } - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 43874 - Scourge Mur'gul Camp: Force Shield Arcane Purple x3 - class spell_q11396_11399_force_shield_arcane_purple_x3 : AuraScript - { - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetImmuneToPC(true); - target.AddUnitState(UnitState.Root); - } - - void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().SetImmuneToPC(false); - } - - public override void Register() - { - OnEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 50133 - Scourging Crystal Controller - class spell_q11396_11399_scourging_crystal_controller : SpellScript - { - const uint SpellForceShieldArcanePurpleX3 = 43874; - const uint SpellScourgingCrystalController = 43878; - - public override bool Validate(SpellInfo spellEntry) - { - return ValidateSpellInfo(SpellForceShieldArcanePurpleX3, SpellScourgingCrystalController); - } - - void HandleDummy(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - if (target.GetTypeId() == TypeId.Unit && target.HasAura(SpellForceShieldArcanePurpleX3)) - // Make sure nobody else is channeling the same target - if (!target.HasAura(SpellScourgingCrystalController)) - GetCaster().CastSpell(target, SpellScourgingCrystalController, GetCastItem()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 43882 - Scourging Crystal Controller Dummy - class spell_q11396_11399_scourging_crystal_controller_dummy : SpellScript - { - const uint SpellForceShieldArcanePurpleX3 = 43874; - - public override bool Validate(SpellInfo spellEntry) - { - return ValidateSpellInfo(SpellForceShieldArcanePurpleX3); - } - - void HandleDummy(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - if (target.GetTypeId() == TypeId.Unit) - target.RemoveAurasDueToSpell(SpellForceShieldArcanePurpleX3); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 46023 - The Ultrasonic Screwdriver - class spell_q11730_ultrasonic_screwdriver : SpellScript - { - const uint SpellSummonScavengebot004A8 = 46063; - const uint SpellSummonSentrybot57K = 46068; - const uint SpellSummonDefendotank66D = 46058; - const uint SpellSummonScavengebot005B6 = 46066; - const uint SpellSummon55DCollectatron = 46034; - const uint SpellRobotKillCredit = 46027; - const uint NpcScavengebot004A8 = 25752; - const uint NpcSentrybot57K = 25753; - const uint NpcDefendotank66D = 25758; - const uint NpcScavengebot005B6 = 25792; - const uint Npc55DCollectatron = 25793; - - public override bool Load() - { - return GetCaster().IsPlayer() && GetCastItem() != null; - } - - public override bool Validate(SpellInfo spellEntry) - { - return ValidateSpellInfo(SpellSummonScavengebot004A8, - SpellSummonSentrybot57K, - SpellSummonDefendotank66D, - SpellSummonScavengebot005B6, - SpellSummon55DCollectatron, - SpellRobotKillCredit - ); - } - - void HandleDummy(uint effIndex) - { - Item castItem = GetCastItem(); - Unit caster = GetCaster(); - Creature target = GetHitCreature(); - if (target != null) - { - uint spellId = target.GetEntry() switch - { - NpcScavengebot004A8 => SpellSummonScavengebot004A8, - NpcSentrybot57K => SpellSummonSentrybot57K, - NpcDefendotank66D => SpellSummonDefendotank66D, - NpcScavengebot005B6 => SpellSummonScavengebot005B6, - Npc55DCollectatron => SpellSummon55DCollectatron, - _ => 0 - }; - - if (spellId == 0) + case CreatureIds.Scavengebot004A8: spellId = SpellIds.SummonScavengebot004A8; break; + case CreatureIds.Sentrybot57K: spellId = SpellIds.SummonSentrybot57K; break; + case CreatureIds.Defendotank66D: spellId = SpellIds.SummonDefendotank66D; break; + case CreatureIds.Scavengebot005B6: spellId = SpellIds.SummonScavengebot005B6; break; + case CreatureIds.Collectatron55D: spellId = SpellIds.Summon55DCollectatron; break; + default: return; - - caster.CastSpell(caster, spellId, castItem); - caster.CastSpell(caster, SpellRobotKillCredit, true); - target.DespawnOrUnsummon(); } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + caster.CastSpell(caster, spellId, castItem); + caster.CastSpell(caster, SpellIds.RobotKillCredit, true); + target.DespawnOrUnsummon(); } } - [Script] // 49587 - Seeds of Nature's Wrath - class spell_q12459_seeds_of_natures_wrath : SpellScript + public override void Register() { - const uint NpcReanimatedFrostwyrm = 26841; - const uint NpcWeakReanimatedFrostwyrm = 27821; - - const uint NpcTurgid = 27808; - const uint NpcWeakTurgid = 27809; - - const uint NpcDeathgaze = 27122; - const uint NpcWeakDeathgaze = 27807; - - void HandleDummy(uint effIndex) - { - Creature creatureTarget = GetHitCreature(); - if (creatureTarget != null) - { - uint uiNewEntry = creatureTarget.GetEntry() switch - { - NpcReanimatedFrostwyrm => NpcWeakReanimatedFrostwyrm, - NpcTurgid => NpcWeakTurgid, - NpcDeathgaze => NpcWeakDeathgaze, - _ => 0 - }; - - if (uiNewEntry != 0) - creatureTarget.UpdateEntry(uiNewEntry); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); } +} - [Script] // 51840 - Despawn Fruit Tosser - class spell_q12634_despawn_fruit_tosser : SpellScript +[Script] // 49587 - Seeds of Nature's Wrath +class spell_q12459_seeds_of_natures_wrath : SpellScript +{ + void HandleDummy(uint effIndex) { - const uint SpellBananasFallToGround = 51836; - const uint SpellOrangeFallsToGround = 51837; - const uint SpellPapayaFallsToGround = 51839; - const uint SpellSummonAdventurousDwarf = 52070; - - public override bool Validate(SpellInfo spellEntry) + Creature creatureTarget = GetHitCreature(); + if (creatureTarget != null) { - return ValidateSpellInfo(SpellBananasFallToGround, - SpellOrangeFallsToGround, - SpellPapayaFallsToGround, - SpellSummonAdventurousDwarf - ); - } - - void HandleDummy(uint effIndex) - { - uint spellId = SpellBananasFallToGround; - switch (RandomHelper.URand(0, 3)) + uint uiNewEntry = 0; + switch (creatureTarget.GetEntry()) { - case 1: - spellId = SpellOrangeFallsToGround; + case CreatureIds.ReanimatedFrostwyrm: + uiNewEntry = CreatureIds.WeakReanimatedFrostwyrm; break; - case 2: - spellId = SpellPapayaFallsToGround; + case CreatureIds.Turgid: + uiNewEntry = CreatureIds.WeakTurgid; + break; + case CreatureIds.Deathgaze: + uiNewEntry = CreatureIds.WeakDeathgaze; break; } - // sometimes, if you're lucky, you get a dwarf - if (RandomHelper.randChance(5)) - spellId = SpellSummonAdventurousDwarf; - GetCaster().CastSpell(GetCaster(), spellId, true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + if (uiNewEntry != 0) + creatureTarget.UpdateEntry(uiNewEntry); } } - [Script] // 54798 - Flaming Arrow Triggered Effect - class spell_q12851_going_bearback : AuraScript + public override void Register() { - const uint NpcFrostgiant = 29351; - const uint NpcFrostworg = 29358; - const uint SpellFrostgiantCredit = 58184; - const uint SpellFrostworgCredit = 58183; - const uint SpellImmolation = 54690; - const uint SpellAblaze = 54683; + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - { - Unit target = GetTarget(); - // Already in fire - if (target.HasAura(SpellAblaze)) - return; - - Player player = caster.GetCharmerOrOwnerPlayerOrPlayerItself(); - if (player != null) - { - switch (target.GetEntry()) - { - case NpcFrostworg: - target.CastSpell(player, SpellFrostworgCredit, true); - target.CastSpell(target, SpellImmolation, true); - target.CastSpell(target, SpellAblaze, true); - break; - case NpcFrostgiant: - target.CastSpell(player, SpellFrostgiantCredit, true); - target.CastSpell(target, SpellImmolation, true); - target.CastSpell(target, SpellAblaze, true); - break; - } - } - } - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleEffectApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); - } +[Script] // 51840 - Despawn Fruit Tosser +class spell_q12634_despawn_fruit_tosser : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BananasFallToGround, SpellIds.OrangeFallsToGround, SpellIds.PapayaFallsToGround, SpellIds.SummonAdventurousDwarf); } - [Script] // 52090 - Ahunae's Knife - class spell_q12659_ahunaes_knife : SpellScript + void HandleDummy(uint effIndex) { - const uint NpcScalpsKcBunny = 28622; - - public override bool Load() + uint spellId = SpellIds.BananasFallToGround; + switch (RandomHelper.URand(0, 3)) { - return GetCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - Creature target = GetHitCreature(); - if (target != null) - { - target.DespawnOrUnsummon(); - caster.KilledMonsterCredit(NpcScalpsKcBunny); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + case 1: spellId = SpellIds.OrangeFallsToGround; break; + case 2: spellId = SpellIds.PapayaFallsToGround; break; } + // sometimes, if you're lucky, you get a dwarf + if (RandomHelper.randChance(5)) + spellId = SpellIds.SummonAdventurousDwarf; + GetCaster().CastSpell(GetCaster(), spellId, true); } - [Script] // 54190 - Lifeblood Dummy - class spell_q12805_lifeblood_dummy : SpellScript + public override void Register() { - const uint NpcShardKillCredit = 29303; - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScript(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - Creature target = GetHitCreature(); - if (target != null) - { - caster.KilledMonsterCredit(NpcShardKillCredit); - target.CastSpell(target, (uint)GetEffectValue(), true); - target.DespawnOrUnsummon(TimeSpan.FromSeconds(2)); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); } +} - // 4338 - Plant Alliance Battle Standard - [Script] // 59643 - Plant Horde Battle Standard - class spell_q13280_13283_plant_battle_standard : SpellScript +[Script] // 54798 - Flaming Arrow Triggered Effect +class spell_q12851_going_bearback : AuraScript +{ + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - const uint NpcKingOfTheMountaintKc = 31766; - const uint SpellPlantHordeBattleStandard = 59643; - const uint SpellHordeBattleStandardState = 59642; - const uint SpellAllianceBattleStandardState = 4339; - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - uint triggeredSpellID = SpellAllianceBattleStandardState; - - caster.HandleEmoteCommand(Emote.OneshotRoar); - if (caster.IsVehicle()) - { - Unit player = caster.GetVehicleKit().GetPassenger(0); - if (player != null) - player.ToPlayer().KilledMonsterCredit(NpcKingOfTheMountaintKc); - } - - if (GetSpellInfo().Id == SpellPlantHordeBattleStandard) - triggeredSpellID = SpellHordeBattleStandardState; - - target.RemoveAllAuras(); - target.CastSpell(target, triggeredSpellID, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 4336 - Jump Jets - class spell_q13280_13283_jump_jets : SpellScript - { - const uint SpellJumpRocketBlast = 4340; - - void HandleCast() - { - Unit caster = GetCaster(); - if (caster.IsVehicle()) - { - Unit rocketBunny = caster.GetVehicleKit().GetPassenger(1); - if (rocketBunny != null) - rocketBunny.CastSpell(rocketBunny, SpellJumpRocketBlast, true); - } - } - - public override void Register() - { - OnCast.Add(new(HandleCast)); - } - } - - [Script] // 50546 - The Focus on the Beach: Ley Line Focus Control Ring Effect - class spell_q12066_bunny_kill_credit : SpellScript - { - const uint SpellBunnyCreditBeam = 47390; - - void HandleDummy(uint effIndex) - { - Creature target = GetHitCreature(); - if (target != null) - target.CastSpell(GetCaster(), SpellBunnyCreditBeam, false); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 49213 - Defending Wyrmrest Temple: Character Script Cast From Gossip - class spell_q12372_cast_from_gossip_trigger : SpellScript - { - const uint SpellSummonWyrmrestDefender = 49207; - - void HandleScript(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), SpellSummonWyrmrestDefender, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 49370 - Wyrmrest Defender: Destabilize Azure Dragonshrine Effect - class spell_q12372_destabilize_azure_dragonshrine_dummy : SpellScript - { - const uint NpcWyrmrestTempleCredit = 27698; - - void HandleDummy(uint effIndex) - { - if (GetHitCreature() != null) - { - Unit caster = GetOriginalCaster(); - if (caster != null) - { - Vehicle vehicle = caster.GetVehicleKit(); - if (vehicle != null) - { - Unit passenger = vehicle.GetPassenger(0); - if (passenger != null) - { - Player player = passenger.ToPlayer(); - if (player != null) - player.KilledMonsterCredit(NpcWyrmrestTempleCredit); - } - } - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 40113 - Knockdown Fel Cannon: The Aggro Check Aura - class spell_q11010_q11102_q11023_aggro_check_AuraScript : AuraScript - { - const uint SpellAggroCheck = 40112; - - void HandleTriggerSpell(AuraEffect aurEff) + Unit caster = GetCaster(); + if (caster != null) { Unit target = GetTarget(); - if (target != null) - // On trigger proccing - target.CastSpell(target, SpellAggroCheck); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleTriggerSpell, 0, AuraType.PeriodicTriggerSpell)); - } - } - - [Script] // 40112 - Knockdown Fel Cannon: The Aggro Check - class spell_q11010_q11102_q11023_aggro_check : SpellScript - { - const uint SpellFlakCannonTrigger = 40110; - - void HandleDummy(uint effIndex) - { - Player playerTarget = GetHitPlayer(); - if (playerTarget != null) - // Check if found player target is on fly mount or using flying form - if (playerTarget.HasAuraType(AuraType.Fly) || playerTarget.HasAuraType(AuraType.ModIncreaseMountedFlightSpeed)) - playerTarget.CastSpell(playerTarget, SpellFlakCannonTrigger, TriggerCastFlags.IgnoreCasterMountedOrOnVehicle); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 40119 - Knockdown Fel Cannon: The Aggro Burst - class spell_q11010_q11102_q11023_aggro_burst : AuraScript - { - const uint SpellChooseLoc = 40056; - - void HandleEffectPeriodic(AuraEffect aurEff) - { - Unit target = GetTarget(); - if (target != null) - // On each tick cast Choose Loc to trigger summon - target.CastSpell(target, SpellChooseLoc); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - } - } - - [Script] // 40056 - Knockdown Fel Cannon: Choose Loc - class spell_q11010_q11102_q11023_choose_loc : SpellScript - { - const uint NpcFelCannon2 = 23082; - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - // Check for player that is in 65 y range - List playerList = caster.GetPlayerListInGrid(65.0f); - foreach (var player in playerList) - { - // Check if found player target is on fly mount or using flying form - if (player.HasAuraType(AuraType.Fly) || player.HasAuraType(AuraType.ModIncreaseMountedFlightSpeed)) - { - // Summom Fel Cannon (bunny version) at found player - caster.SummonCreature(NpcFelCannon2, player.GetPositionX(), player.GetPositionY(), player.GetPositionZ()); - } - } - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // 39844 - Skyguard Blasting Charge - [Script] // 40160 - Throw Bomb - class spell_q11010_q11102_q11023_q11008_check_fly_mount : SpellScript - { - SpellCastResult CheckRequirement() - { - Unit caster = GetCaster(); - // This spell will be cast only if caster has one of these auras - if (!(caster.HasAuraType(AuraType.Fly) || caster.HasAuraType(AuraType.ModIncreaseMountedFlightSpeed))) - return SpellCastResult.CantDoThatRightNow; - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckRequirement)); - } - } - - [Script] // 50894 - Zul'Drak Rat - class spell_q12527_zuldrak_rat : SpellScript - { - const uint SpellSummonGorgedLurkingBasilisk = 50928; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellSummonGorgedLurkingBasilisk); - } - - void HandleScriptEffect(uint effIndex) - { - if (GetHitAura() != null && GetHitAura().GetStackAmount() >= GetSpellInfo().StackAmount) - { - GetHitUnit().CastSpell(null, SpellSummonGorgedLurkingBasilisk, true); - Creature basilisk = GetHitUnit().ToCreature(); - if (basilisk != null) - basilisk.DespawnOrUnsummon(); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 55368 - Summon Stefan - class spell_q12661_q12669_q12676_q12677_q12713_summon_stefan : SpellScript - { - void SetDest(ref SpellDestination dest) - { - // Adjust effect summon position - Position offset = new(0.0f, 0.0f, 20.0f, 0.0f); - dest.RelocateOffset(offset); - } - - public override void Register() - { - OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCasterBack)); - } - } - - [Script] // 53350 - Quenching Mist - class spell_q12730_quenching_mist : AuraScript - { - const uint SpellFlickeringFlames = 53504; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellFlickeringFlames); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - GetTarget().RemoveAurasDueToSpell(SpellFlickeringFlames); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicHeal)); - } - } - - [Script] // 59318 - Grab Fake Soldier - class spell_q13291_q13292_q13239_q13261_frostbrood_skytalon_grab_decoy : SpellScript - { - const uint NpcSkytalon = 31583; - const uint NpcDecoy = 31578; - const uint SpellRide = 59319; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellRide); - } - - void HandleDummy(uint effIndex) - { - if (GetHitCreature() == null) + // Already in fire + if (target.HasAura(SpellIds.Ablaze)) return; - // To Do: Being triggered is hack, but in checkcast it doesn't pass aurastate requirements. - // Beside that the decoy won't keep it's freeze animation state when enter. - GetHitCreature().CastSpell(GetCaster(), SpellRide, true); - } - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 59303 - Summon Frost Wyrm - class spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon : SpellScript - { - void SetDest(ref SpellDestination dest) - { - // Adjust effect summon position - Position offset = new(0.0f, 0.0f, 20.0f, 0.0f); - dest.RelocateOffset(offset); - } - - public override void Register() - { - OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCasterBack)); - } - } - - [Script] // 12601 - Second Chances: Summon Landgren's Soul Moveto Target Bunny - class spell_q12847_summon_soul_moveto_bunny : SpellScript - { - void SetDest(ref SpellDestination dest) - { - // Adjust effect summon position - Position offset = new(0.0f, 0.0f, 2.5f, 0.0f); - dest.RelocateOffset(offset); - } - - public override void Register() - { - OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCaster)); - } - } - - // 57385 - Argent Cannon - [Script] // 57412 - Reckoning Bomb - class spell_q13086_cannons_target : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 0)) - && ValidateSpellInfo((uint)(spellInfo.GetEffect(0).CalcValue())); - } - - void HandleEffectDummy(uint effIndex) - { - WorldLocation pos = GetExplTargetDest(); - if (pos != null) - GetCaster().CastSpell(pos.GetPosition(), (uint)GetEffectValue(), true); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); - } - } - - struct BurstAtTheSeamsIds - { - public const uint AreaTheBrokenFront = 4507; - public const uint AreaMordRetharTheDeathGate = 4508; - - public const uint NpcDrakkariChieftaink = 29099; - public const uint NpcIcyGhoul = 31142; - public const uint NpcViciousGeist = 31147; - public const uint NpcRisenAllianceSoldiers = 31205; - public const uint NpcRenimatedAbomination = 31692; - - public const uint QuestFuelForTheFire = 12690; - - public const uint SpellBloatedAbominationFeignDeath = 52593; - public const uint SpellBurstAtTheSeamsBone = 52516; - public const uint SpellExplodeAbominationMeat = 52520; - public const uint SpellExplodeAbominationBloodyMeat = 52523; - public const uint SpellTrollExplosion = 52565; - public const uint SpellExplodeTrollMeat = 52578; - public const uint SpellExplodeTrollBloodyMeat = 52580; - - public const uint SpellBurstAtTheSeams59576 = 59576; //script/knockback, That's Abominable - public const uint SpellBurstAtTheSeams59579 = 59579; //dummy - public const uint SpellBurstAtTheSeams52510 = 52510; //script/knockback, Fuel for the Fire - public const uint SpellBurstAtTheSeams52508 = 52508; //damage 20000 - public const uint SpellBurstAtTheSeams59580 = 59580; //damage 50000 - - public const uint SpellAssignGhoulKillCreditToMaster = 59590; - public const uint SpellAssignGeistKillCreditToMaster = 60041; - public const uint SpellAssignSkeletonKillCreditToMaster = 60039; - - public const uint SpellDrakkariSkullcrusherCredit = 52590; - public const uint SpellSummonDrakkariChieftain = 52616; - public const uint SpellDrakkariChieftainkKillCredit = 52620; - } - - [Script] // 59576 - Burst at the Seams - class spell_q13264_q13276_q13288_q13289_burst_at_the_seams_59576 : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(BurstAtTheSeamsIds.SpellBurstAtTheSeams59576, BurstAtTheSeamsIds.SpellBloatedAbominationFeignDeath, BurstAtTheSeamsIds.SpellBurstAtTheSeams59579, - BurstAtTheSeamsIds.SpellBurstAtTheSeamsBone, BurstAtTheSeamsIds.SpellExplodeAbominationMeat, BurstAtTheSeamsIds.SpellExplodeAbominationBloodyMeat); - } - - void HandleScript(uint effIndex) - { - Creature creature = GetCaster().ToCreature(); - if (creature != null) - { - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBloatedAbominationFeignDeath, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBurstAtTheSeams59579, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBurstAtTheSeamsBone, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBurstAtTheSeamsBone, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBurstAtTheSeamsBone, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellExplodeAbominationMeat, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellExplodeAbominationBloodyMeat, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellExplodeAbominationBloodyMeat, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellExplodeAbominationBloodyMeat, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 59579 - Burst at the Seams - class spell_q13264_q13276_q13288_q13289_burst_at_the_seams_59579 : AuraScript - { - void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.CastSpell(target, BurstAtTheSeamsIds.SpellTrollExplosion, true); - target.CastSpell(target, BurstAtTheSeamsIds.SpellExplodeAbominationMeat, true); - target.CastSpell(target, BurstAtTheSeamsIds.SpellExplodeTrollMeat, true); - target.CastSpell(target, BurstAtTheSeamsIds.SpellExplodeTrollMeat, true); - target.CastSpell(target, BurstAtTheSeamsIds.SpellExplodeTrollBloodyMeat, true); - target.CastSpell(target, BurstAtTheSeamsIds.SpellBurstAtTheSeamsBone, true); - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - Unit caster = GetCaster(); - if (caster != null) + Player player = caster.GetCharmerOrOwnerPlayerOrPlayerItself(); + if (player != null) { switch (target.GetEntry()) { - case BurstAtTheSeamsIds.NpcIcyGhoul: - target.CastSpell(caster, BurstAtTheSeamsIds.SpellAssignGhoulKillCreditToMaster, true); + case CreatureIds.Frostworg: + target.CastSpell(player, SpellIds.FrostworgCredit, true); + target.CastSpell(target, SpellIds.Immolation, true); + target.CastSpell(target, SpellIds.Ablaze, true); break; - case BurstAtTheSeamsIds.NpcViciousGeist: - target.CastSpell(caster, BurstAtTheSeamsIds.SpellAssignGeistKillCreditToMaster, true); - break; - case BurstAtTheSeamsIds.NpcRisenAllianceSoldiers: - target.CastSpell(caster, BurstAtTheSeamsIds.SpellAssignSkeletonKillCreditToMaster, true); + case CreatureIds.Frostgiant: + target.CastSpell(player, SpellIds.FrostgiantCredit, true); + target.CastSpell(target, SpellIds.Immolation, true); + target.CastSpell(target, SpellIds.Ablaze, true); break; } } - target.CastSpell(target, BurstAtTheSeamsIds.SpellBurstAtTheSeams59580, true); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); } } - [Script] // 52593 - Bloated Abomination Feign Death - class spell_q13264_q13276_q13288_q13289_bloated_abom_feign_death : AuraScript + public override void Register() { - void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.SetUnitFlag3(UnitFlags3.FakeDead); - target.SetUnitFlag2(UnitFlags2.FeignDeath); + AfterEffectApply.Add(new(HandleEffectApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); + } +} - Creature creature = target.ToCreature(); - if (creature != null) - creature.SetReactState(ReactStates.Passive); - } +[Script] // 52090 - Ahunae's Knife +class spell_q12659_ahunaes_knife : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + void HandleDummy(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + Creature target = GetHitCreature(); + if (target != null) { - Unit target = GetTarget(); - Creature creature = target.ToCreature(); - if (creature != null) - creature.DespawnOrUnsummon(); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + target.DespawnOrUnsummon(); + caster.KilledMonsterCredit(CreatureIds.ScalpsKcBunny); } } - [Script] // 76245 - Area Restrict Abom - class spell_q13264_q13276_q13288_q13289_area_restrict_abom : SpellScript + public override void Register() { - void HandleScript(uint effIndex) + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 54190 - Lifeblood Dummy +class spell_q12805_lifeblood_dummy : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScript(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + Creature target = GetHitCreature(); + if (target != null) { - Creature creature = GetHitCreature(); - if (creature != null) + caster.KilledMonsterCredit(CreatureIds.ShardKillCredit); + target.CastSpell(target, (uint)GetEffectValue(), true); + target.DespawnOrUnsummon(TimeSpan.FromSeconds(2)); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +// 4338 - Plant Alliance Battle Standard +[Script] // 59643 - Plant Horde Battle Standard +class spell_q13280_13283_plant_battle_standard : SpellScript +{ + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + uint triggeredSpellId = SpellIds.AllianceBattleStandardState; + + caster.HandleEmoteCommand(Emote.OneshotRoar); + if (caster.IsVehicle()) + { + Unit player = caster.GetVehicleKit().GetPassenger(0); + if (player != null) + player.ToPlayer().KilledMonsterCredit(CreatureIds.KingOfTheMountaintKc); + } + + if (GetSpellInfo().Id == SpellIds.PlantHordeBattleStandard) + triggeredSpellId = SpellIds.HordeBattleStandardState; + + target.RemoveAllAuras(); + target.CastSpell(target, triggeredSpellId, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 4336 - Jump Jets +class spell_q13280_13283_jump_jets : SpellScript +{ + void HandleCast() + { + Unit caster = GetCaster(); + if (caster.IsVehicle()) + { + Unit rocketBunny = caster.GetVehicleKit().GetPassenger(1); + if (rocketBunny != null) + rocketBunny.CastSpell(rocketBunny, SpellIds.JumpRocketBlast, true); + } + } + + public override void Register() + { + OnCast.Add(new(HandleCast)); + } +} + +[Script] // 50546 - The Focus on the Beach: Ley Line Focus Control Ring Effect +class spell_q12066_bunny_kill_credit : SpellScript +{ + void HandleDummy(uint effIndex) + { + Creature target = GetHitCreature(); + if (target != null) + target.CastSpell(GetCaster(), SpellIds.BunnyCreditBeam, false); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 49213 - Defending Wyrmrest Temple: Character Script Cast From Gossip +class spell_q12372_cast_from_gossip_trigger : SpellScript +{ + void HandleScript(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.SummonWyrmrestDefender, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 49370 - Wyrmrest Defender: Destabilize Azure Dragonshrine Effect +class spell_q12372_destabilize_azure_dragonshrine_dummy : SpellScript +{ + void HandleDummy(uint effIndex) + { + if (GetHitCreature() != null) + { + Unit caster = GetOriginalCaster(); + if (caster != null) { - uint area = creature.GetAreaId(); - if (area != BurstAtTheSeamsIds.AreaTheBrokenFront && area != BurstAtTheSeamsIds.AreaMordRetharTheDeathGate) - creature.DespawnOrUnsummon(); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - // 59590 - Assign Ghoul Kill Credit to Master - // 60039 - Assign Skeleton Kill Credit to Master - [Script] // 60041 - Assign Geist Kill Credit to Master - class spell_q13264_q13276_q13288_q13289_assign_credit_to_master : SpellScript - { - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - { - Unit owner = target.GetOwner(); - if (owner != null) + Vehicle vehicle = caster.GetVehicleKit(); + if (vehicle != null) { - owner.CastSpell(owner, (uint)GetEffectValue(), true); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 52510 - Burst at the Seams - class spell_q12690_burst_at_the_seams_52510 : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(BurstAtTheSeamsIds.SpellBurstAtTheSeams52510, BurstAtTheSeamsIds.SpellBurstAtTheSeams52508, BurstAtTheSeamsIds.SpellBurstAtTheSeams59580, - BurstAtTheSeamsIds.SpellBurstAtTheSeamsBone, BurstAtTheSeamsIds.SpellExplodeAbominationMeat, BurstAtTheSeamsIds.SpellExplodeAbominationBloodyMeat); - } - - public override bool Load() - { - return GetCaster().GetTypeId() == TypeId.Unit; - } - - void HandleKnockBack(uint effIndex) - { - Unit creature = GetHitCreature(); - if (creature != null) - { - Unit charmer = GetCaster().GetCharmerOrOwner(); - if (charmer != null) - { - Player player = charmer.ToPlayer(); - if (player != null) + Unit passenger = vehicle.GetPassenger(0); + if (passenger != null) { - if (player.GetQuestStatus(BurstAtTheSeamsIds.QuestFuelForTheFire) == QuestStatus.Incomplete) - { - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBurstAtTheSeamsBone, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellExplodeAbominationMeat, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellExplodeAbominationBloodyMeat, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBurstAtTheSeams52508, true); - creature.CastSpell(creature, BurstAtTheSeamsIds.SpellBurstAtTheSeams59580, true); - - player.CastSpell(player, BurstAtTheSeamsIds.SpellDrakkariSkullcrusherCredit, true); - ushort count = player.GetReqKillOrCastCurrentCount(BurstAtTheSeamsIds.QuestFuelForTheFire, (int)BurstAtTheSeamsIds.NpcDrakkariChieftaink); - if ((count % 20) == 0) - player.CastSpell(player, BurstAtTheSeamsIds.SpellSummonDrakkariChieftain, true); - } + Player player = passenger.ToPlayer(); + if (player != null) + player.KilledMonsterCredit(CreatureIds.WyrmrestTempleCredit); } } } } + } - void HandleScript(uint effIndex) - { - GetCaster().ToCreature().DespawnOrUnsummon(TimeSpan.FromSeconds(2)); - } + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - public override void Register() +[Script] // 40113 - Knockdown Fel Cannon: The Aggro Check Aura +class spell_q11010_q11102_q11023_aggro_check_aura : AuraScript +{ + void HandleTriggerSpell(AuraEffect aurEff) + { + Unit target = GetTarget(); + if (target != null) + // On trigger proccing + target.CastSpell(target, SpellIds.AggroCheck); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleTriggerSpell, 0, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 40112 - Knockdown Fel Cannon: The Aggro Check +class spell_q11010_q11102_q11023_aggro_check : SpellScript +{ + void HandleDummy(uint effIndex) + { + Player playerTarget = GetHitPlayer(); + // Check if found player target is on fly mount or using flying form + if (playerTarget != null && playerTarget.HasAuraType(AuraType.Fly) || playerTarget.HasAuraType(AuraType.ModIncreaseMountedFlightSpeed)) + playerTarget.CastSpell(playerTarget, SpellIds.FlakCannonTrigger, new CastSpellExtraArgs(TriggerCastFlags.IgnoreCasterMountedOrOnVehicle)); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 40119 - Knockdown Fel Cannon: The Aggro Burst +class spell_q11010_q11102_q11023_aggro_burst : AuraScript +{ + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit target = GetTarget(); + if (target != null) + // On each tick cast Choose Loc to trigger summon + target.CastSpell(target, SpellIds.ChooseLoc); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 40056 - Knockdown Fel Cannon: Choose Loc +class spell_q11010_q11102_q11023_choose_loc : SpellScript +{ + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + // Check for player that is in 65 y range + List playerList = caster.GetPlayerListInGrid(65.0f); + foreach (Player player in playerList) { - OnEffectHitTarget.Add(new(HandleKnockBack, 1, SpellEffectName.KnockBack)); - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + // Check if found player target is on fly mount or using flying form + if (player.HasAuraType(AuraType.Fly) || player.HasAuraType(AuraType.ModIncreaseMountedFlightSpeed)) + // Summom Fel Cannon (bunny version) at found player + caster.SummonCreature(CreatureIds.FelCannon2, player.GetPositionX(), player.GetPositionY(), player.GetPositionZ()); } } - [Script] // 48682 - Escape from Silverbrook - Periodic Dummy - class spell_q12308_escape_from_silverbrook : SpellScript + public override void Register() { - const uint SpellSummonWorgen = 48681; + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellSummonWorgen); - } +// 39844 - Skyguard Blasting Charge +[Script] // 40160 - Throw Bomb +class spell_q11010_q11102_q11023_q11008_check_fly_mount : SpellScript +{ + SpellCastResult CheckRequirement() + { + Unit caster = GetCaster(); + // This spell will be cast only if caster has one of these auras + if (!(caster.HasAuraType(AuraType.Fly) || caster.HasAuraType(AuraType.ModIncreaseMountedFlightSpeed))) + return SpellCastResult.CantDoThatRightNow; + return SpellCastResult.SpellCastOk; + } - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), SpellSummonWorgen, true); - } + public override void Register() + { + OnCheckCast.Add(new(CheckRequirement)); + } +} - public override void Register() +[Script] // 50894 - Zul'Drak Rat +class spell_q12527_zuldrak_rat : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SummonGorgedLurkingBasilisk); + } + + void HandleScriptEffect(uint effIndex) + { + if (GetHitAura() != null && GetHitAura().GetStackAmount() >= GetSpellInfo().StackAmount) { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + GetHitUnit().CastSpell(null, SpellIds.SummonGorgedLurkingBasilisk, true); + Creature basilisk = GetHitUnit().ToCreature(); + if (basilisk != null) + basilisk.DespawnOrUnsummon(); } } - [Script] // 48681 - Summon Silverbrook Worgen - class spell_q12308_escape_from_silverbrook_summon_worgen : SpellScript + public override void Register() { - void ModDest(ref SpellDestination dest) - { - float dist = GetEffectInfo(0).CalcRadius(GetCaster()); - float angle = RandomHelper.FRand(0.75f, 1.25f) * (float)(MathF.PI); + OnEffectHitTarget.Add(new(HandleScriptEffect, 1, SpellEffectName.ScriptEffect)); + } +} - Position pos = GetCaster().GetNearPosition(dist, angle); - dest.Relocate(pos); - } +[Script] // 55368 - Summon Stefan +class spell_q12661_q12669_q12676_q12677_q12713_summon_stefan : SpellScript +{ + void SetDest(ref SpellDestination dest) + { + // Adjust effect summon position + Position offset = new(0.0f, 0.0f, 20.0f, 0.0f); + dest.RelocateOffset(offset); + } - public override void Register() + public override void Register() + { + OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCasterBack)); + } +} + +[Script] // 53350 - Quenching Mist +class spell_q12730_quenching_mist : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlickeringFlames); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.FlickeringFlames); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicHeal)); + } +} + +[Script] // 59318 - Grab Fake Soldier +class spell_q13291_q13292_q13239_q13261_frostbrood_skytalon_grab_decoy : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Ride); + } + + void HandleDummy(uint effIndex) + { + if (GetHitCreature() == null) + return; + // To Do: Being triggered is hack, but in checkcast it doesn't pass aurastate requirements. + // Beside that the decoy won't keep it's freeze animation state when enter. + GetHitCreature().CastSpell(GetCaster(), SpellIds.Ride, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 59303 - Summon Frost Wyrm +class spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon : SpellScript +{ + void SetDest(ref SpellDestination dest) + { + // Adjust effect summon position + Position offset = new(0.0f, 0.0f, 20.0f, 0.0f); + dest.RelocateOffset(offset); + } + + public override void Register() + { + OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCasterBack)); + } +} + +[Script] // 12601 - Second Chances: Summon Landgren's Soul Moveto Target Bunny +class spell_q12847_summon_soul_moveto_bunny : SpellScript +{ + void SetDest(ref SpellDestination dest) + { + // Adjust effect summon position + Position offset = new(0.0f, 0.0f, 2.5f, 0.0f); + dest.RelocateOffset(offset); + } + + public override void Register() + { + OnDestinationTargetSelect.Add(new(SetDest, 0, Targets.DestCaster)); + } +} + +// 57385 - Argent Cannon +[Script] // 57412 - Reckoning Bomb +class spell_q13086_cannons_target : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 0)) + && ValidateSpellInfo((uint)spellInfo.GetEffect(0).CalcValue()); + } + + void HandleEffectDummy(uint effIndex) + { + WorldLocation pos = GetExplTargetDest(); + if (pos != null) + GetCaster().CastSpell(pos.GetPosition(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 59576 - Burst at the Seams +class spell_q13264_q13276_q13288_q13289_burst_at_the_seams_59576 : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BurstAtTheSeams59576, SpellIds.BloatedAbominationFeignDeath, SpellIds.BurstAtTheSeams59579, SpellIds.BurstAtTheSeamsBone, SpellIds.ExplodeAbominationMeat, SpellIds.ExplodeAbominationBloodyMeat); + } + + void HandleScript(uint effIndex) + { + Creature creature = GetCaster().ToCreature(); + if (creature != null) { - OnDestinationTargetSelect.Add(new(ModDest, 0, Targets.DestCasterSummon)); + creature.CastSpell(creature, SpellIds.BloatedAbominationFeignDeath, true); + creature.CastSpell(creature, SpellIds.BurstAtTheSeams59579, true); + creature.CastSpell(creature, SpellIds.BurstAtTheSeamsBone, true); + creature.CastSpell(creature, SpellIds.BurstAtTheSeamsBone, true); + creature.CastSpell(creature, SpellIds.BurstAtTheSeamsBone, true); + creature.CastSpell(creature, SpellIds.ExplodeAbominationMeat, true); + creature.CastSpell(creature, SpellIds.ExplodeAbominationBloodyMeat, true); + creature.CastSpell(creature, SpellIds.ExplodeAbominationBloodyMeat, true); + creature.CastSpell(creature, SpellIds.ExplodeAbominationBloodyMeat, true); } } - [Script] // 51858 - Siphon of Acherus - class spell_q12641_death_comes_from_on_high : SpellScript + public override void Register() { - const uint SpellForgeCredit = 51974; - const uint SpellTownHallCredit = 51977; - const uint SpellScarletHoldCredit = 51980; - const uint SpellChapelCredit = 51982; + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} - const uint NpcNewAvalonForge = 28525; - const uint NpcNewAvalonTownHall = 28543; - const uint NpcScarletHold = 28542; - const uint NpcChapelOfTheCrimsonFlame = 28544; +[Script] // 59579 - Burst at the Seams +class spell_q13264_q13276_q13288_q13289_burst_at_the_seams_59579 : AuraScript +{ + void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.TrollExplosion, true); + target.CastSpell(target, SpellIds.ExplodeAbominationMeat, true); + target.CastSpell(target, SpellIds.ExplodeTrollMeat, true); + target.CastSpell(target, SpellIds.ExplodeTrollMeat, true); + target.CastSpell(target, SpellIds.ExplodeTrollBloodyMeat, true); + target.CastSpell(target, SpellIds.BurstAtTheSeamsBone, true); + } - public override bool Validate(SpellInfo spellInfo) + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + Unit caster = GetCaster(); + if (caster != null) { - return ValidateSpellInfo(SpellForgeCredit, SpellTownHallCredit, SpellScarletHoldCredit, SpellChapelCredit); - } - - void HandleDummy(uint effIndex) - { - uint spellId = GetHitCreature().GetEntry() switch + switch (target.GetEntry()) { - NpcNewAvalonForge => SpellForgeCredit, - NpcNewAvalonTownHall => SpellTownHallCredit, - NpcScarletHold => SpellScarletHoldCredit, - NpcChapelOfTheCrimsonFlame => SpellChapelCredit, - _ => 0 - }; - - GetCaster().CastSpell(null, spellId, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 52694 - Recall Eye of Acherus - class spell_q12641_recall_eye_of_acherus : SpellScript - { - const uint TheEyeOfAcherus = 51852; - - void HandleDummy(uint effIndex) - { - Player player = GetCaster().GetCharmerOrOwner().ToPlayer(); - if (player != null) - { - player.StopCastingCharm(); - player.StopCastingBindSight(); - player.RemoveAura(TheEyeOfAcherus); + case CreatureIds.IcyGhoul: + target.CastSpell(caster, SpellIds.AssignGhoulKillCreditToMaster, true); + break; + case CreatureIds.ViciousGeist: + target.CastSpell(caster, SpellIds.AssignGeistKillCreditToMaster, true); + break; + case CreatureIds.RisenAllianceSoldiers: + target.CastSpell(caster, SpellIds.AssignSkeletonKillCreditToMaster, true); + break; } } + target.CastSpell(target, SpellIds.BurstAtTheSeams59580, true); + } - public override void Register() + public override void Register() + { + AfterEffectApply.Add(new(HandleApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 52593 - Bloated Abomination Feign Death +class spell_q13264_q13276_q13288_q13289_bloated_abom_feign_death : AuraScript +{ + void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.SetUnitFlag3(UnitFlags3.FakeDead); + target.SetUnitFlag2(UnitFlags2.FeignDeath); + + Creature creature = target.ToCreature(); + if (target != null) + creature.SetReactState(ReactStates.Passive); + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + Creature creature = target.ToCreature(); + if (target != null) + creature.DespawnOrUnsummon(); + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 76245 - Area Restrict Abom +class spell_q13264_q13276_q13288_q13289_area_restrict_abom : SpellScript +{ + void HandleScript(uint effIndex) + { + Creature creature = GetHitCreature(); + if (creature != null) { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); + uint area = creature.GetAreaId(); + if (area != MiscConst.AreaTheBrokenFront && area != MiscConst.AreaMordRetharTheDeathGate) + creature.DespawnOrUnsummon(); } } - [Script] // 51769 - Emblazon Runeblade - class spell_q12619_emblazon_runeblade : AuraScript + public override void Register() { - void HandleEffectPeriodic(AuraEffect aurEff) - { - PreventDefaultAction(); - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, aurEff.GetSpellEffectInfo().TriggerSpell, aurEff); - } + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} - public override void Register() +// 59590 - Assign Ghoul Kill Credit to Master +// 60039 - Assign Skeleton Kill Credit to Master +[Script] // 60041 - Assign Geist Kill Credit to Master +class spell_q13264_q13276_q13288_q13289_assign_credit_to_master : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); + Unit owner = target.GetOwner(); + if (owner != null) + owner.CastSpell(owner, (uint)GetEffectValue(), true); } } - [Script] // 51770 - Emblazon Runeblade - class spell_q12619_emblazon_runeblade_effect : SpellScript + public override void Register() { - void HandleScript(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), (uint)GetEffectValue(), false); - } + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} - public override void Register() - { - OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } +[Script] // 52510 - Burst at the Seams +class spell_q12690_burst_at_the_seams_52510 : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BurstAtTheSeams52510, SpellIds.BurstAtTheSeams52508, SpellIds.BurstAtTheSeams59580, SpellIds.BurstAtTheSeamsBone, SpellIds.ExplodeAbominationMeat, SpellIds.ExplodeAbominationBloodyMeat); } - [Script] // 55516 - Gymer's Grab - class spell_q12919_gymers_grab : SpellScript + public override bool Load() { - const uint SpellRideGymer = 43671; - const uint SpellGrabbed = 55424; - - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellRideGymer); - } - - void HandleScript(uint effIndex) - { - if (GetHitCreature() == null) - return; - - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, 2); - GetHitCreature().CastSpell(GetCaster(), SpellRideGymer, args); - GetHitCreature().CastSpell(GetHitCreature(), SpellGrabbed, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } + return GetCaster().IsUnit(); } - [Script] // 55421 - Gymer's Throw - class spell_q12919_gymers_throw : SpellScript + void HandleKnockBack(uint effIndex) { - const uint SpellVargulExplosion = 55569; - - void HandleScript(uint effIndex) + Unit creature = GetCaster(); + if (creature != null) { - Unit caster = GetCaster(); - if (caster.IsVehicle()) + Unit charmer = GetCaster().GetCharmerOrOwner(); + if (charmer != null) { - Unit passenger = caster.GetVehicleKit().GetPassenger(1); - if (passenger != null) + Player player = charmer.ToPlayer(); + if (player != null && player.GetQuestStatus(MiscConst.QuestFuelForTheFire) == QuestStatus.Incomplete) { - passenger.ExitVehicle(); - caster.CastSpell(passenger, SpellVargulExplosion, true); + creature.CastSpell(creature, SpellIds.BurstAtTheSeamsBone, true); + creature.CastSpell(creature, SpellIds.ExplodeAbominationMeat, true); + creature.CastSpell(creature, SpellIds.ExplodeAbominationBloodyMeat, true); + creature.CastSpell(creature, SpellIds.BurstAtTheSeams52508, true); + creature.CastSpell(creature, SpellIds.BurstAtTheSeams59580, true); + + player.CastSpell(player, SpellIds.DrakkariSkullcrusherCredit, true); + ushort count = player.GetReqKillOrCastCurrentCount(MiscConst.QuestFuelForTheFire, (int)CreatureIds.DrakkariChieftaink); + if ((count % 20) == 0) + player.CastSpell(player, SpellIds.SummonDrakkariChieftain, true); } } } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } } - [Script] // 61752 - Illidan Kill Credit Master - class spell_q13400_illidan_kill_master : SpellScript + void HandleScript(uint effIndex) { - const uint SpellIllidanKillCredit = 61748; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIllidanKillCredit); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - if (caster.IsVehicle()) - { - Unit passenger = caster.GetVehicleKit().GetPassenger(0); - if (passenger != null) - passenger.CastSpell(passenger, SpellIllidanKillCredit, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + GetCaster().ToCreature().DespawnOrUnsummon(TimeSpan.FromSeconds(2)); } - [Script] // 66744 - Make Player Destroy Totems - class spell_q14100_q14111_make_player_destroy_totems : SpellScript + public override void Register() { - const uint SpellTotemOfTheEarthenRing = 66747; - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellTotemOfTheEarthenRing); - } + OnEffectHitTarget.Add(new(HandleKnockBack, 1, SpellEffectName.KnockBack)); + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} - void HandleScriptEffect(uint effIndex) - { - Player player = GetHitPlayer(); - if (player != null) - player.CastSpell(player, SpellTotemOfTheEarthenRing, TriggerCastFlags.FullMask); // ignore reagent Cost, consumed by quest - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } +[Script] // 48682 - Escape from Silverbrook - Periodic Dummy +class spell_q12308_escape_from_silverbrook : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SummonWorgen); } - [Script] // 39238 - Fuping - class spell_q10929_fuping : AuraScript + void HandleDummy(uint effIndex) { - const uint SpellSummonSandGnome = 39240; - const uint SpellSummonBoneSlicer = 39241; + GetCaster().CastSpell(GetCaster(), SpellIds.SummonWorgen, true); + } - public override bool Validate(SpellInfo spell) - { - return ValidateSpellInfo(SpellSummonSandGnome, SpellSummonBoneSlicer); - } + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) +[Script] // 48681 - Summon Silverbrook Worgen +class spell_q12308_escape_from_silverbrook_summon_worgen : SpellScript +{ + void ModDest(ref SpellDestination dest) + { + float dist = GetEffectInfo(0).CalcRadius(GetCaster()); + float angle = RandomHelper.FRand(0.75f, 1.25f) * MathF.PI; + + Position pos = GetCaster().GetNearPosition(dist, angle); + dest.Relocate(pos); + } + + public override void Register() + { + OnDestinationTargetSelect.Add(new(ModDest, 0, Targets.DestCasterSummon)); + } +} + +[Script] // 51858 - Siphon of Acherus +class spell_q12641_death_comes_from_on_high : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ForgeCredit, SpellIds.TownHallCredit, SpellIds.ScarletHoldCredit, SpellIds.ChapelCredit); + } + + void HandleDummy(uint effIndex) + { + uint spellId = 0; + + switch (GetHitCreature().GetEntry()) { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + case CreatureIds.NewAvalonForge: + spellId = SpellIds.ForgeCredit; + break; + case CreatureIds.NewAvalonTownHall: + spellId = SpellIds.TownHallCredit; + break; + case CreatureIds.ScarletHold: + spellId = SpellIds.ScarletHoldCredit; + break; + case CreatureIds.ChapelOfTheCrimsonFlame: + spellId = SpellIds.ChapelCredit; + break; + default: return; - - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, RandomHelper.URand(SpellSummonSandGnome, SpellSummonBoneSlicer), true); } - public override void Register() + GetCaster().CastSpell(null, spellId, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 52694 - Recall Eye of Acherus +class spell_q12641_recall_eye_of_acherus : SpellScript +{ + void HandleDummy(uint effIndex) + { + Player player = GetCaster().GetCharmerOrOwner().ToPlayer(); + if (player != null) { - OnEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + player.StopCastingCharm(); + player.StopCastingBindSight(); + player.RemoveAura(MiscConst.TheEyeOfAcherus); } } - [Script] // 93072 - Get Our Boys Back Dummy - class spell_q28813_get_our_boys_back_dummy : SpellScript + public override void Register() { - const uint SpellRenewedLife = 93097; - const uint NpcInjuredStormwindInfantry = 50047; - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellRenewedLife); - } + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ScriptEffect)); + } +} - void HandleDummyEffect() - { - Unit caster = GetCaster(); +[Script] // 51769 - Emblazon Runeblade +class spell_q12619_emblazon_runeblade : AuraScript +{ + void HandleEffectPeriodic(AuraEffect aurEff) + { + PreventDefaultAction(); + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, aurEff.GetSpellEffectInfo().TriggerSpell, aurEff); + } - Creature injuredStormwindInfantry = caster.FindNearestCreature(NpcInjuredStormwindInfantry, 5.0f, true); - if (injuredStormwindInfantry != null) + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 51770 - Emblazon Runeblade +class spell_q12619_emblazon_runeblade_effect : SpellScript +{ + void HandleScript(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), (uint)GetEffectValue(), false); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 55516 - Gymer's Grab +class spell_q12919_gymers_grab : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RideGymer); + } + + void HandleScript(uint effIndex) + { + if (GetHitCreature() == null) + return; + + CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); + args.AddSpellMod(SpellValueMod.BasePoint0, 2); + GetHitCreature().CastSpell(GetCaster(), SpellIds.RideGymer, args); + GetHitCreature().CastSpell(GetHitCreature(), SpellIds.Grabbed, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 55421 - Gymer's Throw +class spell_q12919_gymers_throw : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit caster = GetCaster(); + if (caster.IsVehicle()) + { + Unit passenger = caster.GetVehicleKit().GetPassenger(1); + if (passenger != null) { - injuredStormwindInfantry.SetCreatorGUID(caster.GetGUID()); - injuredStormwindInfantry.CastSpell(injuredStormwindInfantry, SpellRenewedLife, true); + passenger.ExitVehicle(); + caster.CastSpell(passenger, SpellIds.VargulExplosion, true); } } + } - public override void Register() + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 61752 - Illidan Kill Credit Master +class spell_q13400_illidan_kill_master : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IllidanKillCredit); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + if (caster.IsVehicle()) { - OnCast.Add(new(HandleDummyEffect)); + Unit passenger = caster.GetVehicleKit().GetPassenger(0); + if (passenger != null) + passenger.CastSpell(passenger, SpellIds.IllidanKillCredit, true); } } - [Script] // 53034 - Set Health Random - class spell_q28813_set_health_random : SpellScript + public override void Register() { - void HandleDummyEffect() - { - Unit caster = GetCaster(); - caster.SetHealth(caster.CountPctFromMaxHealth(RandomHelper.IRand(3, 5) * 10)); - } + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} - public override void Register() +[Script] // 66744 - Make Player Destroy Totems +class spell_q14100_q14111_make_player_destroy_totems : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TotemOfTheEarthenRing); + } + + void HandleScriptEffect(uint effIndex) + { + Player player = GetHitPlayer(); + if (player != null) + player.CastSpell(player, SpellIds.TotemOfTheEarthenRing, new CastSpellExtraArgs(TriggerCastFlags.FullMask)); // ignore reagent cost, consumed by quest + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 39238 - Fumping +class spell_q10929_fumping : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SummonSandGnome, SpellIds.SummonBoneSlicer); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, RandomHelper.URand(SpellIds.SummonSandGnome, SpellIds.SummonBoneSlicer), true); + } + + public override void Register() + { + OnEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 93072 - Get Our Boys Back Dummy +class spell_q28813_get_our_boys_back_dummy : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RenewedLife); + } + + void HandleDummyEffect() + { + Unit caster = GetCaster(); + Creature injuredStormwindInfantry = caster.FindNearestCreature(CreatureIds.InjuredStormwindInfantry, 5.0f, true); + if (injuredStormwindInfantry != null) { - OnCast.Add(new(HandleDummyEffect)); + injuredStormwindInfantry.SetCreatorGUID(caster.GetGUID()); + injuredStormwindInfantry.CastSpell(injuredStormwindInfantry, SpellIds.RenewedLife, true); } } - [Script] // 49285 - Hand Over Reins - class spell_q12414_hand_over_reins : SpellScript + public override void Register() { - void HandleScript(uint effIndex) - { - Creature caster = GetCaster().ToCreature(); - GetHitUnit().ExitVehicle(); + OnCast.Add(new(HandleDummyEffect)); + } +} - if (caster != null) - caster.DespawnOrUnsummon(); - } +[Script] // 53034 - Set Health Random +class spell_q28813_set_health_random : SpellScript +{ + void HandleDummyEffect() + { + Unit caster = GetCaster(); + caster.SetHealth(caster.CountPctFromMaxHealth(RandomHelper.IRand(3, 5) * 10)); + } - public override void Register() + public override void Register() + { + OnCast.Add(new(HandleDummyEffect)); + } +} + +[Script] // 49285 - Hand Over Reins +class spell_q12414_hand_over_reins : SpellScript +{ + void HandleScript(uint effIndex) + { + Creature caster = GetCaster().ToCreature(); + GetHitUnit().ExitVehicle(); + + if (caster != null) + caster.DespawnOrUnsummon(); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); + } +} + +// 13790 13793 13811 13814 - Among the Champions +[Script] // 13665 13745 13750 13756 13761 13767 13772 13777 13782 13787 - The Grand Melee +class spell_q13665_q13790_bested_trigger : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit().GetCharmerOrOwnerOrSelf(); + target.CastSpell(target, (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 43972 - Mixing Blood +class spell_q11306_mixing_blood : SpellScript +{ + void HandleEffect(uint effIndex) + { + Unit caster = GetCaster(); + if (caster != null) { - OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.ScriptEffect)); + Creature trigger = caster.FindNearestCreature(MiscConst.CreatureGenericTriggerLab, 100.0f); + if (trigger != null) + trigger.GetAI().DoCastSelf(SpellIds.SpurtsAndSmoke); } } - // 13790 13793 13811 13814 - Among the Chapions - [Script] // 13665 13745 13750 13756 13761 13767 13772 13777 13782 13787 - The Grand Melee - class spell_q13665_q13790_bested_trigger : SpellScript + public override void Register() { - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit().GetCharmerOrOwnerOrSelf(); - target.CastSpell(target, (uint)GetEffectValue(), true); - } + OnEffectHit.Add(new(HandleEffect, 1, SpellEffectName.SendEvent)); + } +} - public override void Register() +[Script] // 43375 - Mixing Vrykul Blood +class spell_q11306_mixing_vrykul_blood : SpellScript +{ + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + if (caster != null) { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + uint chance = RandomHelper.URand(0, 99); + uint spellId = 0; + + // 90% chance of getting one out of three failure effects + if (chance < 30) + spellId = SpellIds.ErrorMix1; + else if (chance < 60) + spellId = SpellIds.ErrorMix2; + else if (chance < 90) + spellId = SpellIds.ErrorMix3; + else // 10% chance of successful cast + spellId = SpellIds.SuccessfulMix; + + caster.CastSpell(caster, spellId, true); } } - struct ApplyHeatAndStirIds + public override void Register() { - public const uint SpellSpurtsAndSmoke = 38594; - public const uint SpellFailedMix1 = 43376; - public const uint SpellFailedMix2 = 43378; - public const uint SpellFailedMix3 = 43970; - public const uint SpellSuccessfulMix = 43377; + OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); + } +} - public const uint CreatureGenericTriggerLab = 24042; - - public const uint Talk0 = 0; - public const uint Talk1 = 1; +[Script] // 43376 - Failed Mix +class spell_q11306_failed_mix_43376 : SpellScript +{ + void HandleEffect(uint effIndex) + { + Unit caster = GetCaster(); + if (caster != null) + { + Creature trigger = caster.FindNearestCreature(MiscConst.CreatureGenericTriggerLab, 100.0f); + if (trigger != null) + trigger.GetAI().Talk(MiscConst.Talk0, caster); + } } - [Script] // 43972 - Mixing Blood - class spell_q11306_mixing_blood : SpellScript + public override void Register() { - void HandleEffect(uint effIndex) + OnEffectHit.Add(new(HandleEffect, 1, SpellEffectName.SendEvent)); + } +} + +[Script] // 43378 - Failed Mix +class spell_q11306_failed_mix_43378 : SpellScript +{ + void HandleEffect(uint effIndex) + { + Unit caster = GetCaster(); + if (caster != null) { - Unit caster = GetCaster(); - if (caster != null) + Creature trigger = caster.FindNearestCreature(MiscConst.CreatureGenericTriggerLab, 100.0f); + if (trigger != null) + trigger.GetAI().Talk(MiscConst.Talk1, caster); + } + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEffect, 2, SpellEffectName.SendEvent)); + } +} + +[Script] // 46444 - Weakness to Lightning: Cast on Master Script Effect +class spell_q11896_weakness_to_lightning_46444 : SpellScript +{ + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + if (target != null) + { + Unit owner = GetCaster(); + if (owner != null) { - Creature trigger = caster.FindNearestCreature(ApplyHeatAndStirIds.CreatureGenericTriggerLab, 100.0f); - if (trigger != null) - trigger.GetAI().DoCastSelf(ApplyHeatAndStirIds.SpellSpurtsAndSmoke); + target.CastSpell(owner, (uint)GetEffectValue(), true); } } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffect, 1, SpellEffectName.SendEvent)); - } } - [Script] // 43375 - Mixing Vrykul Blood - class spell_q11306_mixing_vrykul_blood : SpellScript + public override void Register() { - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - if (caster != null) - { - uint chance = RandomHelper.URand(0, 99); - uint spellId = 0; + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} - // 90% chance of getting one out of three failure effects - if (chance < 30) - spellId = ApplyHeatAndStirIds.SpellFailedMix1; - else if (chance < 60) - spellId = ApplyHeatAndStirIds.SpellFailedMix2; - else if (chance < 90) - spellId = ApplyHeatAndStirIds.SpellFailedMix3; - else // 10% chance of successful cast - spellId = ApplyHeatAndStirIds.SpellSuccessfulMix; - - caster.CastSpell(caster, spellId, true); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); - } +[Script] +class spell_quest_taming_the_beast : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TameIceClawBear1, SpellIds.TameLargeCragBoar1, SpellIds.TameSnowLeopard1, SpellIds.TameAdultPlainstrider1, SpellIds.TamePrairieStalker1, SpellIds.TameSwoop1, + SpellIds.TameWebwoodLurker1, SpellIds.TameDireMottledBoar1, SpellIds.TameSurfCrawler1, SpellIds.TameArmoredScorpid1, SpellIds.TameNightsaberStalker1, SpellIds.TameStrigidScreecher1, + SpellIds.TameBarbedCrawler1, SpellIds.TameGreaterTimberstrider1, SpellIds.TameNightstalker1, SpellIds.TameCrazedDragonhawk1, SpellIds.TameElderSpringpaw1, SpellIds.TameMistbat1); } - [Script] // 43376 - Failed Mix - class spell_q11306_failed_mix_43376 : SpellScript + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - void HandleEffect(uint effIndex) + if (GetCaster() == null || !GetCaster().IsAlive() || !GetTarget().IsAlive()) + return; + + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) + return; + + uint finalSpellId = 0; + switch (GetId()) { - Unit caster = GetCaster(); - if (caster != null) - { - Creature trigger = caster.FindNearestCreature(ApplyHeatAndStirIds.CreatureGenericTriggerLab, 100.0f); - if (trigger != null) - trigger.GetAI().Talk(ApplyHeatAndStirIds.Talk0, caster); - } + case SpellIds.TameIceClawBear: finalSpellId = SpellIds.TameIceClawBear1; break; + case SpellIds.TameLargeCragBoar: finalSpellId = SpellIds.TameLargeCragBoar1; break; + case SpellIds.TameSnowLeopard: finalSpellId = SpellIds.TameSnowLeopard1; break; + case SpellIds.TameAdultPlainstrider: finalSpellId = SpellIds.TameAdultPlainstrider1; break; + case SpellIds.TamePrairieStalker: finalSpellId = SpellIds.TamePrairieStalker1; break; + case SpellIds.TameSwoop: finalSpellId = SpellIds.TameSwoop1; break; + case SpellIds.TameWebwoodLurker: finalSpellId = SpellIds.TameWebwoodLurker1; break; + case SpellIds.TameDireMottledBoar: finalSpellId = SpellIds.TameDireMottledBoar1; break; + case SpellIds.TameSurfCrawler: finalSpellId = SpellIds.TameSurfCrawler1; break; + case SpellIds.TameArmoredScorpid: finalSpellId = SpellIds.TameArmoredScorpid1; break; + case SpellIds.TameNightsaberStalker: finalSpellId = SpellIds.TameNightsaberStalker1; break; + case SpellIds.TameStrigidScreecher: finalSpellId = SpellIds.TameStrigidScreecher1; break; + case SpellIds.TameBarbedCrawler: finalSpellId = SpellIds.TameBarbedCrawler1; break; + case SpellIds.TameGreaterTimberstrider: finalSpellId = SpellIds.TameGreaterTimberstrider1; break; + case SpellIds.TameNightstalker: finalSpellId = SpellIds.TameNightstalker1; break; + case SpellIds.TameCrazedDragonhawk: finalSpellId = SpellIds.TameCrazedDragonhawk1; break; + case SpellIds.TameElderSpringpaw: finalSpellId = SpellIds.TameElderSpringpaw1; break; + case SpellIds.TameMistbat: finalSpellId = SpellIds.TameMistbat1; break; } - public override void Register() - { - OnEffectHit.Add(new(HandleEffect, 1, SpellEffectName.SendEvent)); - } + if (finalSpellId != 0) + GetCaster().CastSpell(GetTarget(), finalSpellId, true); } - [Script] // 43378 - Failed Mix - class spell_q11306_failed_mix_43378 : SpellScript + public override void Register() { - void HandleEffect(uint effIndex) - { - Unit caster = GetCaster(); - if (caster != null) - { - Creature trigger = caster.FindNearestCreature(ApplyHeatAndStirIds.CreatureGenericTriggerLab, 100.0f); - if (trigger != null) - trigger.GetAI().Talk(ApplyHeatAndStirIds.Talk1, caster); - } - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffect, 2, SpellEffectName.SendEvent)); - } + AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); } +} - [Script] // 46444 - Weakness to Lightning: Cast on Master Script Effect - class spell_q11896_weakness_to_lightning_46444 : SpellScript +[Script] // 53099, 57896, 58418, 58420, 59064, 59065, 59439, 60900, 60940 +class spell_quest_portal_with_condition : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - void HandleScript(uint effIndex) - { - Unit target = GetHitUnit(); - if (target != null) - { - Unit owner = target.GetOwner(); - if (owner != null) - { - target.CastSpell(owner, (uint)GetEffectValue(), true); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } - } - - struct TamingTheBeastIds - { - public const uint IceClawBear = 19548; - public const uint LargeCragBoar = 19674; - public const uint SnowLeopard = 19687; - public const uint AdultPlainstrider = 19688; - public const uint PrairieStalker = 19689; - public const uint Swoop = 19692; - public const uint WebwoodLurker = 19693; - public const uint DireMottledBoar = 19694; - public const uint SurfCrawler = 19696; - public const uint ArmoredScorpid = 19697; - public const uint NightsaberStalker = 19699; - public const uint StrigidScreecher = 19700; - public const uint BarbedCrawler = 30646; - public const uint GreaterTimberstrider = 30653; - public const uint Nightstalker = 30654; - public const uint CrazedDragonhawk = 30099; - public const uint ElderSpringpaw = 30102; - public const uint Mistbat = 30105; - public const uint IceClawBear1 = 19597; - public const uint LargeCragBoar1 = 19677; - public const uint SnowLeopard1 = 19676; - public const uint AdultPlainstrider1 = 19678; - public const uint PrairieStalker1 = 19679; - public const uint Swoop1 = 19680; - public const uint WebwoodLurker1 = 19684; - public const uint DireMottledBoar1 = 19681; - public const uint SurfCrawler1 = 19682; - public const uint ArmoredScorpid1 = 19683; - public const uint NightsaberStalker1 = 19685; - public const uint StrigidScreecher1 = 19686; - public const uint BarbedCrawler1 = 30647; - public const uint GreaterTimberstrider1 = 30648; - public const uint Nightstalker1 = 30652; - public const uint CrazedDragonhawk1 = 30100; - public const uint ElderSpringpaw1 = 30103; - public const uint Mistbat1 = 30104; - } - - [Script] - class spell_quest_taming_the_beast : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(TamingTheBeastIds.IceClawBear1, - TamingTheBeastIds.LargeCragBoar1, - TamingTheBeastIds.SnowLeopard1, - TamingTheBeastIds.AdultPlainstrider1, - TamingTheBeastIds.PrairieStalker1, - TamingTheBeastIds.Swoop1, - TamingTheBeastIds.WebwoodLurker1, - TamingTheBeastIds.DireMottledBoar1, - TamingTheBeastIds.SurfCrawler1, - TamingTheBeastIds.ArmoredScorpid1, - TamingTheBeastIds.NightsaberStalker1, - TamingTheBeastIds.StrigidScreecher1, - TamingTheBeastIds.BarbedCrawler1, - TamingTheBeastIds.GreaterTimberstrider1, - TamingTheBeastIds.Nightstalker1, - TamingTheBeastIds.CrazedDragonhawk1, - TamingTheBeastIds.ElderSpringpaw1, - TamingTheBeastIds.Mistbat1 - ); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetCaster() == null || !GetCaster().IsAlive() || !GetTarget().IsAlive()) - return; - - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire) - return; - - uint finalSpellId = GetId() switch - { - TamingTheBeastIds.IceClawBear => TamingTheBeastIds.IceClawBear1, - TamingTheBeastIds.LargeCragBoar => TamingTheBeastIds.LargeCragBoar1, - TamingTheBeastIds.SnowLeopard => TamingTheBeastIds.SnowLeopard1, - TamingTheBeastIds.AdultPlainstrider => TamingTheBeastIds.AdultPlainstrider1, - TamingTheBeastIds.PrairieStalker => TamingTheBeastIds.PrairieStalker1, - TamingTheBeastIds.Swoop => TamingTheBeastIds.Swoop1, - TamingTheBeastIds.WebwoodLurker => TamingTheBeastIds.WebwoodLurker1, - TamingTheBeastIds.DireMottledBoar => TamingTheBeastIds.DireMottledBoar1, - TamingTheBeastIds.SurfCrawler => TamingTheBeastIds.SurfCrawler1, - TamingTheBeastIds.ArmoredScorpid => TamingTheBeastIds.ArmoredScorpid1, - TamingTheBeastIds.NightsaberStalker => TamingTheBeastIds.NightsaberStalker1, - TamingTheBeastIds.StrigidScreecher => TamingTheBeastIds.StrigidScreecher1, - TamingTheBeastIds.BarbedCrawler => TamingTheBeastIds.BarbedCrawler1, - TamingTheBeastIds.GreaterTimberstrider => TamingTheBeastIds.GreaterTimberstrider1, - TamingTheBeastIds.Nightstalker => TamingTheBeastIds.Nightstalker1, - TamingTheBeastIds.CrazedDragonhawk => TamingTheBeastIds.CrazedDragonhawk1, - TamingTheBeastIds.ElderSpringpaw => TamingTheBeastIds.ElderSpringpaw1, - TamingTheBeastIds.Mistbat => TamingTheBeastIds.Mistbat1, - _ => 0 - }; - - if (finalSpellId != 0) - GetCaster().CastSpell(GetTarget(), finalSpellId, true); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 53099, 57896, 58418, 58420, 59064, 59065, 59439, 60900, 60940 - class spell_quest_portal_with_condition : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)) + return ValidateSpellEffect((spellInfo.Id, 1)) && ValidateSpellInfo((uint)spellInfo.GetEffect(0).CalcValue()) - && ObjectMgr.GetQuestTemplate((uint)spellInfo.GetEffect(1).CalcValue()) != null; - } - - void HandleScriptEffect(uint effIndex) - { - Player target = GetHitPlayer(); - if (target == null) - return; - - uint spellId = (uint)GetEffectInfo().CalcValue(); - uint questId = (uint)GetEffectInfo(1).CalcValue(); - - // This probably should be a way to throw error in SpellCastResult - if (target.IsActiveQuest(questId)) - target.CastSpell(target, spellId, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } + && Global.ObjectMgr.GetQuestTemplate((uint)spellInfo.GetEffect(1).CalcValue()) != null; } - struct TributeSpellIds + void HandleScriptEffect(uint effIndex) { - public const uint GromsTrollTribute = 24101; - public const uint GromsTaurenTribute = 24102; - public const uint GromsUndeadTribute = 24103; - public const uint GromsOrcTribute = 24104; - public const uint GromsBloodelfTribute = 69530; - public const uint UthersHumanTribute = 24105; - public const uint UthersGnomeTribute = 24106; - public const uint UthersDwarfTribute = 24107; - public const uint UthersNightelfTribute = 24108; - public const uint UthersDraeneiTribute = 69533; + Player target = GetHitPlayer(); + if (target == null) + return; + + uint spellId = (uint)GetEffectInfo().CalcValue(); + uint questId = (uint)GetEffectInfo(1).CalcValue(); + + // This probably should be a way to throw error in SpellCastResult + if (target.IsActiveQuest(questId)) + target.CastSpell(target, spellId, true); } - // 24194 - Uther's Tribute - [Script] // 24195 - Grom's Tribute - class spell_quest_uther_grom_tribute : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(TributeSpellIds.GromsTrollTribute, TributeSpellIds.UthersHumanTribute, - TributeSpellIds.GromsTaurenTribute, TributeSpellIds.UthersGnomeTribute, - TributeSpellIds.GromsUndeadTribute, TributeSpellIds.UthersDwarfTribute, - TributeSpellIds.GromsOrcTribute, TributeSpellIds.UthersNightelfTribute, - TributeSpellIds.GromsBloodelfTribute, TributeSpellIds.UthersDraeneiTribute); - } - - void HandleScript(uint effIndex) - { - Player caster = GetCaster().ToPlayer(); - if (caster == null) - return; - - uint spell = caster.GetRace() switch - { - Race.Troll => TributeSpellIds.GromsTrollTribute, - Race.Tauren => TributeSpellIds.GromsTaurenTribute, - Race.Undead => TributeSpellIds.GromsUndeadTribute, - Race.Orc => TributeSpellIds.GromsOrcTribute, - Race.BloodElf => TributeSpellIds.GromsBloodelfTribute, - Race.Human => TributeSpellIds.UthersHumanTribute, - Race.Gnome => TributeSpellIds.UthersGnomeTribute, - Race.Dwarf => TributeSpellIds.UthersDwarfTribute, - Race.NightElf => TributeSpellIds.UthersNightelfTribute, - Race.Draenei => TributeSpellIds.UthersDraeneiTribute, - _ => 0, - }; - - if (spell != 0) - caster.CastSpell(caster, spell); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); - } + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); } +} - [Script] // 68682 Call Attack Mastiffs - class spell_q14386_call_attack_mastiffs : SpellScript +// 24194 - Uther's Tribute +[Script] // 24195 - Grom's Tribute +class spell_quest_uther_grom_tribute : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) { - const uint NpcAttackMastiff = 36405; - - void HandleEffect(uint eff) - { - Unit caster = GetCaster(); - caster.SummonCreature(NpcAttackMastiff, -1944.573f, 2657.402f, 0.994939f, 1.691919f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -2005.65f, 2663.526f, -2.086935f, 0.5942355f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -1996.506f, 2651.347f, -1.011707f, 0.8185352f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -1972.352f, 2640.07f, 1.080288f, 1.217854f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -1949.322f, 2642.76f, 1.242482f, 1.58074f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -1993.94f, 2672.535f, -2.322549f, 0.5766209f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -1982.724f, 2662.8f, -1.773986f, 0.8628055f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -1973.301f, 2655.475f, -0.7831049f, 1.098415f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - caster.SummonCreature(NpcAttackMastiff, -1956.509f, 2650.655f, 1.350571f, 1.441473f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleEffect, 1, SpellEffectName.SendEvent)); - } + return ValidateSpellInfo(SpellIds.GromsTrollTribute, SpellIds.UthersHumanTribute, SpellIds.GromsTaurenTribute, SpellIds.UthersGnomeTribute, SpellIds.GromsUndeadTribute, SpellIds.UthersDwarfTribute, + SpellIds.GromsOrcTribute, SpellIds.UthersNightelfTribute, SpellIds.GromsBloodelfTribute, SpellIds.UthersDraeneiTribute); } -} \ No newline at end of file + + void HandleScript(uint effIndex) + { + Player caster = GetCaster().ToPlayer(); + if (caster == null) + return; + + uint spell = 0; + switch (caster.GetRace()) + { + case Race.Troll: + spell = SpellIds.GromsTrollTribute; + break; + case Race.Tauren: + spell = SpellIds.GromsTaurenTribute; + break; + case Race.Undead: + spell = SpellIds.GromsUndeadTribute; + break; + case Race.Orc: + spell = SpellIds.GromsOrcTribute; + break; + case Race.BloodElf: + spell = SpellIds.GromsBloodelfTribute; + break; + case Race.Human: + spell = SpellIds.UthersHumanTribute; + break; + case Race.Gnome: + spell = SpellIds.UthersGnomeTribute; + break; + case Race.Dwarf: + spell = SpellIds.UthersDwarfTribute; + break; + case Race.NightElf: + spell = SpellIds.UthersNightelfTribute; + break; + case Race.Draenei: + spell = SpellIds.UthersDraeneiTribute; + break; + default: break; + } + + if (spell != 0) + caster.CastSpell(caster, spell); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleScript, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 68682 Call Attack Mastiffs +class spell_q14386_call_attack_mastiffs : SpellScript +{ + void HandleEffect(uint effIndex) + { + Unit caster = GetCaster(); + caster.SummonCreature(CreatureIds.AttackMastiff, -1944.573f, 2657.402f, 0.994939f, 1.691919f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -2005.65f, 2663.526f, -2.086935f, 0.5942355f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -1996.506f, 2651.347f, -1.011707f, 0.8185352f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -1972.352f, 2640.07f, 1.080288f, 1.217854f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -1949.322f, 2642.76f, 1.242482f, 1.58074f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -1993.94f, 2672.535f, -2.322549f, 0.5766209f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -1982.724f, 2662.8f, -1.773986f, 0.8628055f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -1973.301f, 2655.475f, -0.7831049f, 1.098415f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + caster.SummonCreature(CreatureIds.AttackMastiff, -1956.509f, 2650.655f, 1.350571f, 1.441473f, TempSummonType.TimedDespawnOutOfCombat, TimeSpan.FromSeconds(1)); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEffect, 1, SpellEffectName.SendEvent)); + } +} diff --git a/Source/Scripts/Spells/Rogue.cs b/Source/Scripts/Spells/Rogue.cs index 83d75d015..2d53858fb 100644 --- a/Source/Scripts/Spells/Rogue.cs +++ b/Source/Scripts/Spells/Rogue.cs @@ -1,1063 +1,1502 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; -using Framework.Dynamic; -using Game.DataStorage; using Game.Entities; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using static Global; -namespace Scripts.Spells.Rogue +namespace Scripts.Spells.Rogue; + +struct SpellIds { + public const uint AcrobaticStrikesProc = 455144; + public const uint AdrenalineRush = 13750; + public const uint AirborneIrritant = 200733; + public const uint AmplifyingPoison = 381664; + public const uint AmplifyingPoisonDebuff = 383414; + public const uint AtrophicPoison = 381637; + public const uint AtrophicPoisonDebuff = 392388; + public const uint BetweenTheEyes = 199804; + public const uint BlackjackTalent = 379005; + public const uint Blackjack = 394119; + public const uint BladeFlurry = 13877; + public const uint BladeFlurryExtraAttack = 22482; + public const uint BlindArea = 427773; + public const uint Broadside = 193356; + public const uint BuriedTreasure = 199600; + public const uint CheatDeathDummy = 31231; + public const uint CheatedDeath = 45181; + public const uint CheatingDeath = 45182; + public const uint CloakedInShadowsTalent = 382515; + public const uint CloakedInShadowsAbsorb = 386165; + public const uint CripplingPoison = 3408; + public const uint CripplingPoisonDebuff = 3409; + public const uint DeadlyPoison = 2823; + public const uint DeadlyPoisonDebuff = 2818; + public const uint DeadlyPoisonInstantDamage = 113780; + public const uint GrandMelee = 193358; + public const uint GrapplingHook = 195457; + public const uint ImprovedGarroteAfterStealth = 392401; + public const uint ImprovedGarroteStealth = 392403; + public const uint ImprovedGarroteTalent = 381632; + public const uint ImprovedShiv = 319032; + public const uint InstantPoison = 315584; + public const uint InstantPoisonDamage = 315585; + public const uint KillingSpree = 51690; + public const uint KillingSpreeTeleport = 57840; + public const uint KillingSpreeWeaponDmg = 57841; + public const uint KillingSpreeDmgBuff = 61851; + public const uint MarkedForDeath = 137619; + public const uint MainGauche = 86392; + public const uint NightTerrors = 277953; + public const uint NumbingPoison = 5761; + public const uint NumbingPoisonDebuff = 5760; + public const uint PremeditationPassive = 343160; + public const uint PremeditationAura = 343173; + public const uint PremeditationEnergize = 343170; + public const uint PreyOnTheWeakTalent = 131511; + public const uint PreyOnTheWeak = 255909; + public const uint RuthlessPrecision = 193357; + public const uint Sanctuary = 98877; + public const uint SkullAndCrossbones = 199603; + public const uint ShadowDance = 185313; + public const uint ShadowFocus = 108209; + public const uint ShadowFocusEffect = 112942; + public const uint ShadowsGrasp = 206760; + public const uint ShivNatureDamage = 319504; + public const uint ShotInTheDarkTalent = 257505; + public const uint ShotInTheDarkBuff = 257506; + public const uint ShurikenStormDamage = 197835; + public const uint ShurikenStormEnergize = 212743; + public const uint SliceAndDice = 315496; + public const uint Sprint = 2983; + public const uint SoothingDarknessTalent = 393970; + public const uint SoothingDarknessHeal = 393971; + public const uint Stealth = 1784; + public const uint StealthStealthAura = 158185; + public const uint StealthShapeshiftAura = 158188; + public const uint SymbolsOfDeathCritAura = 227151; + public const uint SymbolsOfDeathRANK2 = 328077; + public const uint TrueBearing = 193359; + public const uint TurnTheTablesBuff = 198027; + public const uint Vanish = 1856; + public const uint VanishAura = 11327; + public const uint TricksOfTheTrade = 57934; + public const uint TricksOfTheTradeProc = 59628; + public const uint HonorAmongThievesEnergize = 51699; + public const uint T5_2PSetBonus = 37169; + public const uint VenomousWounds = 79134; + public const uint WoundPoison = 8679; + public const uint WoundPoisonDebuff = 8680; - struct SpellIds + public static (uint, uint)[] PoisonAuraToDebuff = { - public const uint AdrenalineRush = 13750; - public const uint BetweenTheEyes = 199804; - public const uint BlackjackTalent = 379005; - public const uint Blackjack = 394119; - public const uint BladeFlurry = 13877; - public const uint BladeFlurryExtraAttack = 22482; - public const uint Broadside = 193356; - public const uint BuriedTreasure = 199600; - public const uint CheatDeathDummy = 31231; - public const uint CheatedDeath = 45181; - public const uint CheatingDeath = 45182; - public const uint DeathFromAbove = 152150; - public const uint GrandMelee = 193358; - public const uint GrapplingHook = 195457; - public const uint ImrovedShiv = 319032; - public const uint KillingSpree = 51690; - public const uint KillingSpreeTeleport = 57840; - public const uint KillingSpreeWeaponDmg = 57841; - public const uint KillingSpreeDmgBuff = 61851; - public const uint MarkedForDeath = 137619; - public const uint MasterOfSubtletyDamagePercent = 31665; - public const uint MasterOfSubtletyPassive = 31223; - public const uint MainGauche = 86392; - public const uint PremeditationPassive = 343160; - public const uint PremeditationAura = 343173; - public const uint PreyOnTheWeakTalent = 131511; - public const uint PreyOnTheWeak = 255909; - public const uint RuthlessPrecision = 193357; - public const uint Sanctuary = 98877; - public const uint SkullAndCrossbones = 199603; - public const uint ShadowFocus = 108209; - public const uint ShadowFocusEffect = 112942; - public const uint ShivNatureDamage = 319504; - public const uint SliceAndDice = 315496; - public const uint Sprint = 2983; - public const uint Stealth = 1784; - public const uint StealthStealthAura = 158185; - public const uint StealthShapeshiftAura = 158188; - public const uint SymbolsOfDeathCritAura = 227151; - public const uint SymbolsOfDeathRank2 = 328077; - public const uint TrueBearing = 193359; - public const uint TurnTheTablesBuff = 198027; - public const uint Vanish = 1856; - public const uint VanishAura = 11327; - public const uint TricksOfTheTrade = 57934; - public const uint TricksOfTheTradeProc = 59628; - public const uint HonorAmongThievesEnergize = 51699; - public const uint T52PSetBonus = 37169; - public const uint VenomousWounds = 79134; + (WoundPoison, WoundPoisonDebuff), + (DeadlyPoison, DeadlyPoisonDebuff), + (AmplifyingPoison, AmplifyingPoisonDebuff), + (CripplingPoison, CripplingPoisonDebuff), + (NumbingPoison, NumbingPoisonDebuff), + (InstantPoison, InstantPoisonDamage), + (AtrophicPoison, AtrophicPoisonDebuff), + }; +} + +[Script] // 455143 - Acrobatic Strikes +class spell_rog_acrobatic_strikes : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AcrobaticStrikesProc); } - struct Misc + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public static int? GetFinishingMoveCPCost(Spell spell) + GetTarget().CastSpell(GetTarget(), SpellIds.AcrobaticStrikesProc, new CastSpellExtraArgs() { - if (spell == null) - return null; + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } - return spell.GetPowerTypeCostAmount(PowerType.ComboPoints); + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // Called by 2094 - Blind +class spell_rog_airborne_irritant : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AirborneIrritant, SpellIds.BlindArea); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.AirborneIrritant); + } + + void HandleHit(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.BlindArea, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleHit, 0, SpellEffectName.ApplyAura)); + } +} + +[Script] // 427773 - Blind +class spell_rog_airborne_irritant_target_selection : SpellScript +{ + void FilterTargets(List targets) + { + targets.Remove(GetExplTargetWorldObject()); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, SpellConst.EffectAll, Targets.UnitDestAreaEnemy)); + } +} + +[Script] // 53 - Backstab +class spell_rog_backstab : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 3)); + } + + void HandleHitDamage(uint effIndex) + { + Unit hitUnit = GetHitUnit(); + if (hitUnit == null) + return; + + Unit caster = GetCaster(); + if (hitUnit.IsInBack(caster)) + { + float currDamage = (float)GetHitDamage(); + float newDamage = MathFunctions.AddPct(ref currDamage, (float)GetEffectInfo(3).CalcValue(caster)); + SetHitDamage((int)newDamage); } } - [Script] // 53 - Backstab - class spell_rog_backstab : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnEffectHitTarget.Add(new(HandleHitDamage, 1, SpellEffectName.SchoolDamage)); + } +} + +// 379005 - Blackjack +[Script] // Called by Sap - 6770 and Blind - 2094 +class spell_rog_blackjack : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BlackjackTalent, SpellIds.Blackjack); + } + + void EffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + if (caster.HasAura(SpellIds.BlackjackTalent)) + caster.CastSpell(GetTarget(), SpellIds.Blackjack, true); + } + + public override void Register() + { + AfterEffectRemove.Add(new(EffectRemove, 0, AuraType.Any, AuraEffectHandleModes.Real)); + } +} + +[Script] // 13877, 33735, (check 51211, 65956) - Blade Flurry +class spell_rog_blade_flurry : AuraScript +{ + Unit _procTarget; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BladeFlurryExtraAttack); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + _procTarget = GetTarget().SelectNearbyTarget(eventInfo.GetProcTarget()); + return _procTarget != null && eventInfo.GetDamageInfo() != null; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo != null) { - return ValidateSpellEffect((spellInfo.Id, 3)); + CastSpellExtraArgs args = new(aurEff); + args.AddSpellMod(SpellValueMod.BasePoint0, (int)damageInfo.GetDamage()); + GetTarget().CastSpell(_procTarget, SpellIds.BladeFlurryExtraAttack, args); + } + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + if (m_scriptSpellId == SpellIds.BladeFlurry) + OnEffectProc.Add(new(HandleProc, 0, AuraType.ModPowerRegenPercent)); + else + OnEffectProc.Add(new(HandleProc, 0, AuraType.ModMeleeHaste)); + } +} + +[Script] // 31230 - Cheat Death +class spell_rog_cheat_death : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CheatDeathDummy, SpellIds.CheatedDeath, SpellIds.CheatingDeath) + && ValidateSpellEffect((spellInfo.Id, 1)); + } + + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + Unit target = GetTarget(); + if (target.HasAura(SpellIds.CheatedDeath)) + { + absorbAmount = 0; + return; } - void HandleHitDamage(uint effIndex) - { - Unit hitUnit = GetHitUnit(); - if (hitUnit == null) - return; + PreventDefaultAction(); - Unit caster = GetCaster(); - if (hitUnit.IsInBack(caster)) + target.CastSpell(target, SpellIds.CheatDeathDummy, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + target.CastSpell(target, SpellIds.CheatedDeath, TriggerCastFlags.DontReportCastError); + target.CastSpell(target, SpellIds.CheatingDeath, TriggerCastFlags.DontReportCastError); + + target.SetHealth(target.CountPctFromMaxHealth(GetEffectInfo(1).CalcValue(target))); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + } +} + +[Script] // 382515 - Cloaked in Shadows (attached to 1856 - Vanish) +class spell_rog_cloaked_in_shadows : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CloakedInShadowsAbsorb) + && ValidateSpellEffect((SpellIds.CloakedInShadowsTalent, 0)); + } + + public override bool Load() + { + return GetCaster().HasAuraEffect(SpellIds.CloakedInShadowsTalent, 0); + } + + void HandleCloakedInShadows() + { + Unit caster = GetCaster(); + + AuraEffect cloakedInShadows = caster.GetAuraEffect(SpellIds.CloakedInShadowsTalent, 0); + if (cloakedInShadows == null) + return; + + int amount = (int)caster.CountPctFromMaxHealth(cloakedInShadows.GetAmount()); + + caster.CastSpell(caster, SpellIds.CloakedInShadowsAbsorb, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell(), + SpellValueOverrides = { new(SpellValueMod.BasePoint0, amount) } + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleCloakedInShadows)); + } +} + +[Script] // 2818 - Deadly Poison +class spell_rog_deadly_poison : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DeadlyPoisonInstantDamage); + } + + void HandleInstantDamage(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target.HasAura(GetSpellInfo().Id, caster.GetGUID())) + { + caster.CastSpell(target, SpellIds.DeadlyPoisonInstantDamage, new CastSpellExtraArgs() { - float currDamage = (float)(GetHitDamage()); - float newDamage = MathFunctions.AddPct(ref currDamage, (float)(GetEffectInfo(3).CalcValue(caster))); - SetHitDamage((int)newDamage); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHitDamage, 1, SpellEffectName.SchoolDamage)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); } } - // 379005 - Blackjack - [Script] // Called by Sap - 6770 and Blind - 2094 - class spell_rog_blackjack : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.BlackjackTalent, SpellIds.Blackjack); - } + OnEffectLaunchTarget.Add(new(HandleInstantDamage, 0, SpellEffectName.ApplyAura)); + } +} - void EffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - if (caster.HasAura(SpellIds.BlackjackTalent)) - caster.CastSpell(GetTarget(), SpellIds.Blackjack, true); - } - - public override void Register() - { - AfterEffectRemove.Add(new(EffectRemove, 0, AuraType.Any, AuraEffectHandleModes.Real)); - } +[Script] // 185314 - Deepening Shadows +class spell_rog_deepening_shadows : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowDance); } - [Script] // 13877, 33735, (check 51211, 65956) - Blade Flurry - class spell_rog_blade_flurry : AuraScript + static bool CheckProc(AuraEffect aurEff, ProcEventInfo procEvent) { - Unit _procTarget; + Spell procSpell = procEvent.GetProcSpell(); + if (procSpell != null) + return procSpell.GetPowerTypeCostAmount(PowerType.ComboPoints) > 0; - public override bool Validate(SpellInfo spellInfo) + return false; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + TimeSpan amount = -TimeSpan.FromSeconds(aurEff.GetAmount()) * procInfo.GetProcSpell().GetPowerTypeCostAmount(PowerType.ComboPoints).Value; + GetTarget().GetSpellHistory().ModifyChargeRecoveryTime(Global.SpellMgr.GetSpellInfo(SpellIds.ShadowDance, GetCastDifficulty()).ChargeCategoryId, amount / 10); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 32645 - Envenom +class spell_rog_envenom : SpellScript +{ + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + pctMod *= GetSpell().GetPowerTypeCostAmount(PowerType.ComboPoints).GetValueOrDefault(0); + + AuraEffect t5 = GetCaster().GetAuraEffect(SpellIds.T5_2PSetBonus, 0); + if (t5 != null) + flatMod += t5.GetAmount(); + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamage)); + } +} + +[Script] // 196819 - Eviscerate +class spell_rog_eviscerate : SpellScript +{ + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + pctMod *= GetSpell().GetPowerTypeCostAmount(PowerType.ComboPoints).GetValueOrDefault(0); + + AuraEffect t5 = GetCaster().GetAuraEffect(SpellIds.T5_2PSetBonus, 0); + if (t5 != null) + flatMod += t5.GetAmount(); + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamage)); + } +} + +[Script] // 193358 - Grand Melee +class spell_rog_grand_melee : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SliceAndDice); + } + + bool HandleCheckProc(ProcEventInfo eventInfo) + { + Spell procSpell = eventInfo.GetProcSpell(); + return procSpell != null && procSpell.HasPowerTypeCost(PowerType.ComboPoints); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Spell procSpell = procInfo.GetProcSpell(); + int amount = aurEff.GetAmount() * procSpell.GetPowerTypeCostAmount(PowerType.ComboPoints).Value * 1000; + + Unit target = GetTarget(); + if (target != null) { - return ValidateSpellInfo(SpellIds.BladeFlurryExtraAttack); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - _procTarget = GetTarget().SelectNearbyTarget(eventInfo.GetProcTarget()); - return _procTarget != null && eventInfo.GetDamageInfo() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo != null) - { - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)damageInfo.GetDamage()); - GetTarget().CastSpell(_procTarget, SpellIds.BladeFlurryExtraAttack, args); - } - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - if (m_scriptSpellId == SpellIds.BladeFlurry) - OnEffectProc.Add(new(HandleProc, 0, AuraType.ModPowerRegenPercent)); + Aura aura = target.GetAura(SpellIds.SliceAndDice); + if (aura != null) + aura.SetDuration(aura.GetDuration() + amount); else - OnEffectProc.Add(new(HandleProc, 0, AuraType.ModMeleeHaste)); + { + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.Duration, amount); + target.CastSpell(target, SpellIds.SliceAndDice, args); + } } } - [Script] // 31230 - Cheat Death - class spell_rog_cheat_death : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + DoCheckProc.Add(new(HandleCheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +// 198031 - Honor Among Thieves +[Script] /// 7.1.5 +class spell_rog_honor_among_thieves : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.HonorAmongThievesEnergize); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.HonorAmongThievesEnergize, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // Called by 1784 - Stealth +class spell_rog_improved_garrote : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImprovedGarroteAfterStealth, SpellIds.ImprovedGarroteStealth, SpellIds.ImprovedGarroteTalent); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ImprovedGarroteTalent); + } + + void HandleBuff(uint spellToCast, uint auraToRemove) + { + Unit target = GetTarget(); + + target.RemoveAurasDueToSpell(auraToRemove); + target.CastSpell(target, spellToCast, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.CheatDeathDummy, SpellIds.CheatedDeath, SpellIds.CheatingDeath) - && ValidateSpellEffect((spellInfo.Id, 1)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); - void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + } + + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + HandleBuff(SpellIds.ImprovedGarroteStealth, SpellIds.ImprovedGarroteAfterStealth); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + HandleBuff(SpellIds.ImprovedGarroteAfterStealth, SpellIds.ImprovedGarroteStealth); + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleEffectApply, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(HandleEffectRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 703 - Garrote +class spell_rog_improved_garrote_damage : AuraScript +{ + float _pctMod = 1.0f; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImprovedGarroteAfterStealth, SpellIds.ImprovedGarroteStealth, SpellIds.ImprovedGarroteTalent); + } + + void CalculateBonus(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + _pctMod = 1.0f; + Unit caster = GetCaster(); + if (caster == null) + return; + + AuraEffect improvedGarroteStealth = caster.GetAuraEffect(SpellIds.ImprovedGarroteAfterStealth, 1); + if (improvedGarroteStealth != null) + MathFunctions.AddPct(ref _pctMod, improvedGarroteStealth.GetAmount()); + else { - Unit target = GetTarget(); - if (target.HasAura(SpellIds.CheatedDeath)) - { - absorbAmount = 0; - return; - } - - PreventDefaultAction(); - - target.CastSpell(target, SpellIds.CheatDeathDummy, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); - target.CastSpell(target, SpellIds.CheatedDeath, TriggerCastFlags.DontReportCastError); - target.CastSpell(target, SpellIds.CheatingDeath, TriggerCastFlags.DontReportCastError); - - target.SetHealth(target.CountPctFromMaxHealth(GetEffectInfo(1).CalcValue(target))); - } - - public override void Register() - { - OnEffectAbsorb.Add(new(HandleAbsorb, 0)); + AuraEffect improvedGarroteAfterStealth = caster.GetAuraEffect(SpellIds.ImprovedGarroteStealth, 1); + if (improvedGarroteAfterStealth != null) + MathFunctions.AddPct(ref _pctMod, improvedGarroteAfterStealth.GetAmount()); } } - [Script] // 2818 - Deadly Poison - class spell_rog_deadly_poison : SpellScript + void CalculateDamage(AuraEffect aurEff, Unit victim, ref int damage, ref int flatMod, ref float pctMod) { - byte _stackAmount; + pctMod *= _pctMod; + } - public override bool Load() + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateBonus, 0, AuraType.PeriodicDamage)); + DoEffectCalcDamageAndHealing.Add(new(CalculateDamage, 0, AuraType.PeriodicDamage)); + } +} + +[Script] // 5938 - Shiv +class spell_rog_improved_shiv : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShivNatureDamage); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ImprovedShiv); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ShivNatureDamage, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 51690 - Killing Spree +class spell_rog_killing_spree_aura : AuraScript +{ + List _targets = new(); + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.KillingSpreeTeleport, SpellIds.KillingSpreeWeaponDmg, SpellIds.KillingSpreeDmgBuff); + } + + void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().CastSpell(GetTarget(), SpellIds.KillingSpreeDmgBuff, true); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + while (!_targets.Empty()) { - // at this point CastItem must already be initialized - return GetCaster().IsPlayer() && GetCastItem() != null; - } - - void HandleBeforeHit(SpellMissInfo missInfo) - { - if (missInfo != SpellMissInfo.None) - return; - - Unit target = GetHitUnit(); + ObjectGuid guid = _targets.SelectRandom(); + Unit target = Global.ObjAccessor.GetUnit(GetTarget(), guid); if (target != null) { - // Deadly Poison - AuraEffect aurEff = target.GetAuraEffect(AuraType.PeriodicDamage, SpellFamilyNames.Rogue, new FlagArray128(0x10000, 0x80000, 0), GetCaster().GetGUID()); - if (aurEff != null) - _stackAmount = aurEff.GetBase().GetStackAmount(); + GetTarget().CastSpell(target, SpellIds.KillingSpreeTeleport, true); + GetTarget().CastSpell(target, SpellIds.KillingSpreeWeaponDmg, true); + break; } + else + _targets.Remove(guid); } + } - void HandleAfterHit() + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.KillingSpreeDmgBuff); + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); + } + + public + void AddTarget(Unit target) + { + _targets.Add(target.GetGUID()); + } +} + +[Script] +class spell_rog_killing_spree : SpellScript +{ + void FilterTargets(List targets) + { + if (targets.Empty() || GetCaster().GetVehicleBase() != null) + FinishCast(SpellCastResult.OutOfRange); + } + + void HandleDummy(uint effIndex) + { + Aura aura = GetCaster().GetAura(SpellIds.KillingSpree); + if (aura != null) { - if (_stackAmount < 5) - return; + spell_rog_killing_spree_aura script = aura.GetScript(); + if (script != null) + script.AddTarget(GetHitUnit()); + } + } - Player player = GetCaster().ToPlayer(); + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); + } +} - Unit target = GetHitUnit(); - if (target != null) +[Script] // 385627 - Kingsbane +class spell_rog_kingsbane : AuraScript +{ + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + return procInfo.GetActionTarget().HasAura(GetId(), GetCasterGUID()); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 4, AuraType.ProcTriggerSpell)); ; + } +} + +[Script] // 76806 - Mastery: Main Gauche +class spell_rog_mastery_main_gauche : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MainGauche); + } + + bool HandleCheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetDamageInfo() != null && eventInfo.GetDamageInfo().GetVictim() != null; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Unit target = GetTarget(); + if (target != null) + target.CastSpell(procInfo.GetDamageInfo().GetVictim(), SpellIds.MainGauche, aurEff); + } + + public override void Register() + { + DoCheckProc.Add(new(HandleCheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 277953 - Night Terrors (attached to 197835 - Shuriken Storm) +class spell_rog_night_terrors : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NightTerrors, SpellIds.ShadowsGrasp); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.NightTerrors); + } + + void HandleEnergize(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ShadowsGrasp, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEnergize, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] +class spell_rog_pickpocket : SpellScript +{ + SpellCastResult CheckCast() + { + if (GetExplTargetUnit() == null || !GetCaster().IsValidAttackTarget(GetExplTargetUnit(), GetSpellInfo())) + return SpellCastResult.BadTargets; + + return SpellCastResult.SpellCastOk; + } + + public override void Register() + { + OnCheckCast.Add(new(CheckCast)); + } +} + +[Script] // 185565 - Poisoned Knife +class spell_rog_poisoned_knife : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo + ( + SpellIds.WoundPoison, + SpellIds.WoundPoisonDebuff, + SpellIds.DeadlyPoison, + SpellIds.DeadlyPoisonDebuff, + SpellIds.AmplifyingPoison, + SpellIds.AmplifyingPoisonDebuff, + SpellIds.CripplingPoison, + SpellIds.CripplingPoisonDebuff, + SpellIds.NumbingPoison, + SpellIds.NumbingPoisonDebuff, + SpellIds.InstantPoison, + SpellIds.InstantPoisonDamage, + SpellIds.AtrophicPoison, + SpellIds.AtrophicPoisonDebuff + ); + } + + void HandleHit(uint effIndex) + { + Unit caster = GetCaster(); + foreach (var (poisonAura, debuffSpellId) in SpellIds.PoisonAuraToDebuff) + { + if (caster.HasAura(poisonAura)) { - - Item item = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.MainHand); - - if (item == GetCastItem()) - item = player.GetItemByPos(InventorySlots.Bag0, EquipmentSlot.OffHand); - - if (item == null) - return; - - // item combat enchantments - for (EnchantmentSlot slot = 0; slot < EnchantmentSlot.Max; ++slot) + caster.CastSpell(GetHitUnit(), debuffSpellId, new CastSpellExtraArgs() { - SpellItemEnchantmentRecord enchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(item.GetEnchantmentId(slot)); - if (enchant == null) - continue; - - for (byte s = 0; s < 3; ++s) - { - if (enchant.Effect[s] != ItemEnchantmentType.CombatSpell) - continue; - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(enchant.EffectArg[s], Difficulty.None); - if (spellInfo == null) - { - Log.outError(LogFilter.Spells, $"Player.CastItemCombatSpell Enchant {enchant.Id}, player (Name: {player.GetName()}, {player.GetGUID().ToString()})cast unknown spell {enchant.EffectArg[s]}"); - continue; - } - - // Proc only rogue poisons - if (spellInfo.SpellFamilyName != SpellFamilyNames.Rogue || spellInfo.Dispel != DispelType.Poison) - continue; - - // Do not reproc deadly - if (spellInfo.SpellFamilyFlags & new FlagArray128(0x10000)) - continue; - - if (spellInfo.IsPositive()) - player.CastSpell(player, enchant.EffectArg[s], item); - else - player.CastSpell(target, enchant.EffectArg[s], item); - } - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } } - - public override void Register() - { - BeforeHit.Add(new(HandleBeforeHit)); - AfterHit.Add(new(HandleAfterHit)); - } } - [Script] // 32645 - Envenom - class spell_rog_envenom : SpellScript + public override void Register() { - void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - pctMod *= GetSpell().GetPowerTypeCostAmount(PowerType.ComboPoints).GetValueOrDefault(0); + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); + } +} - AuraEffect t5 = GetCaster().GetAuraEffect(SpellIds.T52PSetBonus, 0); - if (t5 != null) - flatMod += t5.GetAmount(); - } - - public override void Register() - { - CalcDamage.Add(new(CalculateDamage)); - } +[Script] // Called by 1784 - Stealth +class spell_rog_premeditation : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PremeditationPassive, SpellIds.PremeditationAura); } - [Script] // 196819 - Eviscerate - class spell_rog_eviscerate : SpellScript + public override bool Load() { - void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) - { - pctMod *= GetSpell().GetPowerTypeCostAmount(PowerType.ComboPoints).GetValueOrDefault(0); - - AuraEffect t5 = GetCaster().GetAuraEffect(SpellIds.T52PSetBonus, 0); - if (t5 != null) - flatMod += t5.GetAmount(); - } - - public override void Register() - { - CalcDamage.Add(new(CalculateDamage)); - } + return GetCaster().HasAura(SpellIds.PremeditationPassive); } - [Script] // 193358 - Grand Melee - class spell_rog_grand_melee : AuraScript + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) + GetCaster().CastSpell(GetCaster(), SpellIds.PremeditationAura, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.SliceAndDice); - } - - bool HandleCheckProc(ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - return procSpell != null && procSpell.HasPowerTypeCost(PowerType.ComboPoints); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Spell procSpell = procInfo.GetProcSpell(); - int amount = aurEff.GetAmount() * procSpell.GetPowerTypeCostAmount(PowerType.ComboPoints).Value * 1000; - - Unit target = GetTarget(); - if (target != null) - { - Aura aura = target.GetAura(SpellIds.SliceAndDice); - if (aura != null) - aura.SetDuration(aura.GetDuration() + amount); - else - { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.Duration, amount); - target.CastSpell(target, SpellIds.SliceAndDice, args); - } - } - } - - public override void Register() - { - DoCheckProc.Add(new(HandleCheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); } - // 198031 - Honor Among Thieves - [Script] // 7.1.5 - class spell_rog_honor_among_thieves : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.HonorAmongThievesEnergize); - } + AfterEffectApply.Add(new(HandleEffectApply, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit target = GetTarget(); - target.CastSpell(target, SpellIds.HonorAmongThievesEnergize, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 343173 - Premeditation (proc) +class spell_rog_premeditation_proc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PremeditationEnergize); } - [Script] // 5938 - Shiv - class spell_rog_improved_shiv : SpellScript + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) { - public override bool Validate(SpellInfo spellInfo) + GetCaster().CastSpell(GetCaster(), SpellIds.PremeditationEnergize, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.ShivNatureDamage); - } - - public override bool Load() - { - return GetCaster().HasAura(SpellIds.ImrovedShiv); - } - - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.ShivNatureDamage, new CastSpellExtraArgs() - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) - .SetTriggeringSpell(GetSpell())); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.SchoolDamage)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); } - [Script] // 51690 - Killing Spree - class spell_rog_killing_spree_AuraScript : AuraScript + public override void Register() { - List _targets = new(); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.KillingSpreeTeleport, - SpellIds.KillingSpreeWeaponDmg, - SpellIds.KillingSpreeDmgBuff - ); - } - - void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().CastSpell(GetTarget(), SpellIds.KillingSpreeDmgBuff, true); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - while (!_targets.Empty()) - { - ObjectGuid guid = _targets.SelectRandom(); - Unit target = ObjAccessor.GetUnit(GetTarget(), guid); - if (target != null) - { - GetTarget().CastSpell(target, SpellIds.KillingSpreeTeleport, true); - GetTarget().CastSpell(target, SpellIds.KillingSpreeWeaponDmg, true); - break; - } - else - _targets.Remove(guid); - } - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.KillingSpreeDmgBuff); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); - } - - public void AddTarget(Unit target) - { - _targets.Add(target.GetGUID()); - } +// 131511 - Prey on the Weak +[Script] // Called by Cheap Shot - 1833 and Kidney Shot - 408 +class spell_rog_prey_on_the_weak : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PreyOnTheWeakTalent, SpellIds.PreyOnTheWeak); } - [Script] - class spell_rog_killing_spree : SpellScript + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - void FilterTargets(List targets) - { - if (targets.Empty() || GetCaster().GetVehicleBase() != null) - FinishCast(SpellCastResult.OutOfRange); - } - - void HandleDummy(uint effIndex) - { - Aura aura = GetCaster().GetAura(SpellIds.KillingSpree); - if (aura != null) - { - spell_rog_killing_spree_AuraScript script = aura.GetScript(); - if (script != null) - script.AddTarget(GetHitUnit()); - } - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy)); - } + Unit caster = GetCaster(); + if (caster != null) + if (caster.HasAura(SpellIds.PreyOnTheWeakTalent)) + caster.CastSpell(GetTarget(), SpellIds.PreyOnTheWeak, true); } - [Script] // 385627 - Kingsbane - class spell_rog_kingsbane : AuraScript + public override void Register() { - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - return procInfo.GetActionTarget().HasAura(GetId(), GetCasterGUID()); - } + AfterEffectApply.Add(new(OnApply, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); + } +} - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 4, AuraType.ProcTriggerSpell)); - } +[Script] // 79096 - Restless Blades +class spell_rog_restless_blades : AuraScript +{ + static uint[] Spells = [SpellIds.AdrenalineRush, SpellIds.BetweenTheEyes, SpellIds.Sprint, SpellIds.GrapplingHook, SpellIds.Vanish, SpellIds.KillingSpree, SpellIds.MarkedForDeath]; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(Spells); } - [Script] // 76806 - Mastery: Main Gauche - class spell_rog_mastery_main_gauche : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) { - public override bool Validate(SpellInfo spellInfo) + var spentCp = procInfo.GetProcSpell()?.GetPowerTypeCostAmount(PowerType.ComboPoints); + if (spentCp.HasValue) { - return ValidateSpellInfo(SpellIds.MainGauche); - } + int cdExtra = -(int)((float)(aurEff.GetAmount() * spentCp.Value) * 0.1f); - bool HandleCheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetDamageInfo()?.GetVictim() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Unit target = GetTarget(); - if (target != null) - target.CastSpell(procInfo.GetDamageInfo().GetVictim(), SpellIds.MainGauche, aurEff); - } - - public override void Register() - { - DoCheckProc.Add(new(HandleCheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] - class spell_rog_pickpocket : SpellScript - { - SpellCastResult CheckCast() - { - if (GetExplTargetUnit() == null || !GetCaster().IsValidAttackTarget(GetExplTargetUnit(), GetSpellInfo())) - return SpellCastResult.BadTargets; - - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - } - } - - // 131511 - Prey on the Weak - [Script] // Called by Cheap Shot - 1833 and Kidney Shot - 408 - class spell_rog_prey_on_the_weak : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PreyOnTheWeakTalent, SpellIds.PreyOnTheWeak); - } - - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster != null) - if (caster.HasAura(SpellIds.PreyOnTheWeakTalent)) - caster.CastSpell(GetTarget(), SpellIds.PreyOnTheWeak, true); - } - - public override void Register() - { - AfterEffectApply.Add(new(OnApply, 0, AuraType.ModStun, AuraEffectHandleModes.Real)); - } - } - - [Script] // 79096 - Restless Blades - class spell_rog_restless_blades : AuraScript - { - uint[] Spells = { SpellIds.AdrenalineRush, SpellIds.BetweenTheEyes, SpellIds.Sprint, SpellIds.GrapplingHook, SpellIds.Vanish, SpellIds.KillingSpree, SpellIds.MarkedForDeath, SpellIds.DeathFromAbove }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(Spells); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - var spentCP = Misc.GetFinishingMoveCPCost(procInfo.GetProcSpell()); - if (spentCP.HasValue) - { - int cdExtra = -(int)((float)(aurEff.GetAmount() * spentCP.Value) * 0.1f); - - SpellHistory history = GetTarget().GetSpellHistory(); - foreach (uint spellId in Spells) - history.ModifyCooldown(spellId, TimeSpan.FromSeconds(cdExtra), true); - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 315508 - Roll the Bones - class spell_rog_roll_the_bones : SpellScript - { - uint[] Spells = { SpellIds.SkullAndCrossbones, SpellIds.GrandMelee, SpellIds.RuthlessPrecision, SpellIds.TrueBearing, SpellIds.BuriedTreasure, SpellIds.Broadside }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(Spells); - } - - void HandleDummy(uint effIndex) - { - int currentDuration = 0; + SpellHistory history = GetTarget().GetSpellHistory(); foreach (uint spellId in Spells) - { - Aura aura = GetCaster().GetAura(spellId); - if (aura != null) - { - currentDuration = aura.GetDuration(); - GetCaster().RemoveAura(aura); - } - } - - List possibleBuffs = new(Spells); - possibleBuffs.Shuffle(); - - // https://www.icy-veins.com/wow/outlaw-rogue-pve-dps-rotation-cooldowns-abilities - // 1 Roll the Bones buff : 100.0 % chance; - // 2 Roll the Bones buffs : 19 % chance; - // 5 Roll the Bones buffs : 1 % chance. - int chance = RandomHelper.IRand(1, 100); - int numBuffs = 1; - if (chance <= 1) - numBuffs = 5; - else if (chance <= 20) - numBuffs = 2; - - for (int i = 0; i < numBuffs; ++i) - { - uint spellId = possibleBuffs[i]; - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.Duration, GetSpellInfo().GetDuration() + currentDuration); - GetCaster().CastSpell(GetCaster(), spellId, args); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ApplyAura)); + history.ModifyCooldown(spellId, TimeSpan.FromSeconds(cdExtra), true); } } - [Script] // 1943 - Rupture - class spell_rog_rupture : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.VenomousWounds); - } + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} - void OnEffectRemoved(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) - return; +[Script] // 315508 - Roll the Bones +class spell_rog_roll_the_bones : SpellScript +{ + static uint[] Spells = [SpellIds.SkullAndCrossbones, SpellIds.GrandMelee, SpellIds.RuthlessPrecision, SpellIds.TrueBearing, SpellIds.BuriedTreasure, SpellIds.Broadside]; - Aura aura = GetAura(); - Unit caster = aura.GetCaster(); - if (caster == null) - return; - - Aura auraVenomousWounds = caster.GetAura(SpellIds.VenomousWounds); - if (auraVenomousWounds == null) - return; - - // Venomous Wounds: if unit dies while being affected by rupture, regain energy based on remaining duration - var cost = GetSpellInfo().CalcPowerCost(PowerType.Energy, false, caster, GetSpellInfo().GetSchoolMask(), null); - if (cost == null) - return; - - float pct = (float)(aura.GetDuration()) / (float)(aura.GetMaxDuration()); - int extraAmount = (int)((float)(cost.Amount) * pct); - caster.ModifyPower(PowerType.Energy, extraAmount); - } - - public override void Register() - { - OnEffectRemove.Add(new(OnEffectRemoved, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); - } + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(Spells); } - [Script] // 14161 - Ruthlessness - class spell_rog_ruthlessness : AuraScript + void HandleDummy(uint effIndex) { - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + int currentDuration = 0; + foreach (uint spellId in Spells) { - Unit target = GetTarget(); - - var cost = Misc.GetFinishingMoveCPCost(procInfo.GetProcSpell()); - if (cost.HasValue) - if (RandomHelper.randChance(aurEff.GetSpellEffectInfo().PointsPerResource * cost.Value)) - target.ModifyPower(PowerType.ComboPoints, 1); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 185438 - Shadowstrike - class spell_rog_shadowstrike : SpellScript - { - bool _hasPremeditationAura; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PremeditationAura, SpellIds.SliceAndDice, SpellIds.PremeditationPassive) - && ValidateSpellEffect((SpellIds.PremeditationPassive, 0)); - } - - SpellCastResult HandleCheckCast() - { - // Because the premeditation aura is Removed when we're out of stealth, - // when we reach HandleEnergize the aura won't be there, even if it was when player launched the spell - _hasPremeditationAura = GetCaster().HasAura(SpellIds.PremeditationAura); - return SpellCastResult.Success; - } - - void HandleEnergize(uint effIndex) - { - Unit caster = GetCaster(); - if (_hasPremeditationAura) - { - if (caster.HasAura(SpellIds.SliceAndDice)) - { - Aura premeditationPassive = caster.GetAura(SpellIds.PremeditationPassive); - if (premeditationPassive != null) - { - AuraEffect auraEff = premeditationPassive.GetEffect(1); - if (auraEff != null) - SetHitDamage(GetHitDamage() + auraEff.GetAmount()); - } - } - - // Grant 10 seconds of slice and dice - int duration = SpellMgr.GetSpellInfo(SpellIds.PremeditationPassive, Difficulty.None).GetEffect(0).CalcValue(GetCaster()); - - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.Duration, duration * Time.InMilliseconds); - caster.CastSpell(caster, SpellIds.SliceAndDice, args); - } - } - - public override void Register() - { - OnCheckCast.Add(new(HandleCheckCast)); - OnEffectHitTarget.Add(new(HandleEnergize, 1, SpellEffectName.Energize)); - } - } - - [Script] // 193315 - Sinister Strike - class spell_rog_sinister_strike : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.T52PSetBonus); - } - - void HandleDummy(uint effIndex) - { - int damagePerCombo = GetHitDamage(); - AuraEffect t5 = GetCaster().GetAuraEffect(SpellIds.T52PSetBonus, 0); - if (t5 != null) - damagePerCombo += t5.GetAmount(); - - int finalDamage = damagePerCombo; - int? comboPointCost = GetSpell().GetPowerTypeCostAmount(PowerType.ComboPoints); - if (comboPointCost.HasValue) - finalDamage *= comboPointCost.Value; - - SetHitDamage(finalDamage); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 2, SpellEffectName.Dummy)); - } - } - - [Script] // 1784 - Stealth - class spell_rog_stealth : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MasterOfSubtletyPassive, - SpellIds.MasterOfSubtletyDamagePercent, - SpellIds.Sanctuary, - SpellIds.ShadowFocus, - SpellIds.ShadowFocusEffect, - SpellIds.StealthStealthAura, - SpellIds.StealthShapeshiftAura - ); - } - - void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - - // Master of Subtlety - if (target.HasAura(SpellIds.MasterOfSubtletyPassive)) - target.CastSpell(target, SpellIds.MasterOfSubtletyDamagePercent, TriggerCastFlags.FullMask); - - // Shadow Focus - if (target.HasAura(SpellIds.ShadowFocus)) - target.CastSpell(target, SpellIds.ShadowFocusEffect, TriggerCastFlags.FullMask); - - // Premeditation - if (target.HasAura(SpellIds.PremeditationPassive)) - target.CastSpell(target, SpellIds.PremeditationAura, true); - - target.CastSpell(target, SpellIds.Sanctuary, TriggerCastFlags.FullMask); - target.CastSpell(target, SpellIds.StealthStealthAura, TriggerCastFlags.FullMask); - target.CastSpell(target, SpellIds.StealthShapeshiftAura, TriggerCastFlags.FullMask); - } - - void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - - // Master of Subtlety - AuraEffect masterOfSubtletyPassive = GetTarget().GetAuraEffect(SpellIds.MasterOfSubtletyPassive, 0); - if (masterOfSubtletyPassive != null) - { - Aura masterOfSubtletyAura = GetTarget().GetAura(SpellIds.MasterOfSubtletyDamagePercent); - if (masterOfSubtletyAura != null) - { - masterOfSubtletyAura.SetMaxDuration(masterOfSubtletyPassive.GetAmount()); - masterOfSubtletyAura.RefreshDuration(); - } - } - - // Premeditation - target.RemoveAura(SpellIds.PremeditationAura); - - target.RemoveAurasDueToSpell(SpellIds.ShadowFocusEffect); - target.RemoveAurasDueToSpell(SpellIds.StealthStealthAura); - target.RemoveAurasDueToSpell(SpellIds.StealthShapeshiftAura); - } - - public override void Register() - { - AfterEffectApply.Add(new(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } - } - - [Script] // 212283 - Symbols of Death - class spell_rog_symbols_of_death : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SymbolsOfDeathRank2, SpellIds.SymbolsOfDeathCritAura); - } - - void HandleEffectHitTarget(uint effIndex) - { - if (GetCaster().HasAura(SpellIds.SymbolsOfDeathRank2)) - GetCaster().CastSpell(GetCaster(), SpellIds.SymbolsOfDeathCritAura, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.ApplyAura)); - } - } - - [Script] // 57934 - Tricks of the Trade - class spell_rog_tricks_of_the_trade_AuraScript : AuraScript - { - ObjectGuid _redirectTarget; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.TricksOfTheTradeProc); - } - - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Default || !GetTarget().HasAura(SpellIds.TricksOfTheTradeProc)) - GetTarget().GetThreatManager().UnregisterRedirectThreat(SpellIds.TricksOfTheTrade); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit rogue = GetTarget(); - if (ObjAccessor.GetUnit(rogue, _redirectTarget) != null) - rogue.CastSpell(rogue, SpellIds.TricksOfTheTradeProc, aurEff); - Remove(AuraRemoveMode.Default); - } - - public override void Register() - { - AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - - public void SetRedirectTarget(ObjectGuid guid) { _redirectTarget = guid; } - } - - [Script] // 57934 - Tricks of the Trade - class spell_rog_tricks_of_the_trade : SpellScript - { - void DoAfterHit() - { - Aura aura = GetHitAura(); + Aura aura = GetCaster().GetAura(spellId); if (aura != null) { - var script = aura.GetScript(); - if (script != null) + currentDuration = aura.GetDuration(); + GetCaster().RemoveAura(aura); + } + } + + List possibleBuffs = new(Spells); + possibleBuffs.RandomShuffle(); + + // https://www.icy-veins.com/wow/outlaw-rogue-pve-dps-rotation-cooldowns-abilities + // 1 Roll the Bones buff : 100.0 % chance; + // 2 Roll the Bones buffs : 19 % chance; + // 5 Roll the Bones buffs : 1 % chance. + int chance = RandomHelper.IRand(1, 100); + int numBuffs = 1; + if (chance <= 1) + numBuffs = 5; + else if (chance <= 20) + numBuffs = 2; + + for (int i = 0; i < numBuffs; ++i) + { + uint spellId = possibleBuffs[i]; + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.Duration, GetSpellInfo().GetDuration() + currentDuration); + GetCaster().CastSpell(GetCaster(), spellId, args); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.ApplyAura)); + } +} + +[Script] // 1943 - Rupture +class spell_rog_rupture : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VenomousWounds); + } + + void OnEffectRemoved(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) + return; + + Aura aura = GetAura(); + Unit caster = aura.GetCaster(); + if (caster == null) + return; + + Aura auraVenomousWounds = caster.GetAura(SpellIds.VenomousWounds); + if (auraVenomousWounds == null) + return; + + // Venomous Wounds: if unit dies while being affected by rupture, regain energy based on remaining duration + var cost = GetSpellInfo().CalcPowerCost(PowerType.Energy, false, caster, GetSpellInfo().GetSchoolMask(), null); + if (cost == null) + return; + + float pct = (float)aura.GetDuration() / (float)aura.GetMaxDuration(); + int extraAmount = (int)((float)cost.Amount * pct); + caster.ModifyPower(PowerType.Energy, extraAmount); + } + + public override void Register() + { + OnEffectRemove.Add(new(OnEffectRemoved, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); + } +} + +[Script] // 14161 - Ruthlessness +class spell_rog_ruthlessness : AuraScript +{ + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Unit target = GetTarget(); + + var cost = procInfo.GetProcSpell()?.GetPowerTypeCostAmount(PowerType.ComboPoints); + if (cost.HasValue) + if (RandomHelper.randChance(aurEff.GetSpellEffectInfo().PointsPerResource * cost.Value)) + target.ModifyPower(PowerType.ComboPoints, 1); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 185438 - Shadowstrike +class spell_rog_shadowstrike : SpellScript +{ + bool _hasPremeditationAura; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PremeditationAura, SpellIds.SliceAndDice, SpellIds.PremeditationPassive) + && ValidateSpellEffect((SpellIds.PremeditationPassive, 0)); + } + + SpellCastResult HandleCheckCast() + { + // Because the premeditation aura is removed when we're out of stealth, + // when we reach HandleEnergize the aura won't be there, even if it was when player launched the spell + _hasPremeditationAura = GetCaster().HasAura(SpellIds.PremeditationAura); + return SpellCastResult.Success; + } + + void HandleEnergize(uint effIndex) + { + Unit caster = GetCaster(); + if (_hasPremeditationAura) + { + if (caster.HasAura(SpellIds.SliceAndDice)) + { + Aura premeditationPassive = caster.GetAura(SpellIds.PremeditationPassive); + if (premeditationPassive != null) { - Unit explTarget = GetExplTargetUnit(); - if (explTarget != null) - script.SetRedirectTarget(explTarget.GetGUID()); - else - script.SetRedirectTarget(ObjectGuid.Empty); + AuraEffect auraEff = premeditationPassive.GetEffect(1); + if (auraEff != null) + SetHitDamage(GetHitDamage() + auraEff.GetAmount()); } } - } - public override void Register() - { - AfterHit.Add(new(DoAfterHit)); + // Grant 10 seconds of slice and dice + int duration = Global.SpellMgr.GetSpellInfo(SpellIds.PremeditationPassive, Difficulty.None).GetEffect(0).CalcValue(GetCaster()); + + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.Duration, duration * Time.InMilliseconds); + caster.CastSpell(caster, SpellIds.SliceAndDice, args); } } - [Script] // 59628 - Tricks of the Trade (Proc) - class spell_rog_tricks_of_the_trade_proc : AuraScript + public override void Register() { - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + OnCheckCast.Add(new(HandleCheckCast)); + OnEffectHitTarget.Add(new(HandleEnergize, 1, SpellEffectName.Energize)); + } +} + +[Script] // Called by 1784 - Stealth and 185313 - Shadow Dance +class spell_rog_shadow_focus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowFocus, SpellIds.ShadowFocusEffect); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ShadowFocus); + } + + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().CastSpell(GetTarget(), SpellIds.ShadowFocusEffect, new CastSpellExtraArgs() { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.ShadowFocusEffect); + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleEffectApply, 1, AuraType.Any, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(HandleEffectRemove, 1, AuraType.Any, AuraEffectHandleModes.Real)); + } +} + +[Script] // 257505 - Shot in the Dark (attached to 1784 - Stealth and 185313 - Shadow Dance) +class spell_rog_shot_in_the_dark : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShotInTheDarkTalent, SpellIds.ShotInTheDarkBuff); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ShotInTheDarkTalent); + } + + void HandleAfterCast() + { + Unit caster = GetCaster(); + caster.CastSpell(caster, SpellIds.ShotInTheDarkBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 257506 - Shot in the Dark (attached to 185422 - Shadow Dance and 158185 - Stealth) +class spell_rog_shot_in_the_dark_buff : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShotInTheDarkBuff); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().RemoveAurasDueToSpell(SpellIds.ShotInTheDarkBuff); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Any, AuraEffectHandleModes.Real)); + } +} + +[Script] // 197835 - Shuriken Storm +class spell_rog_shuriken_storm : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShurikenStormEnergize); + } + + void HandleEnergize(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.ShurikenStormEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell(), + SpellValueOverrides = { new(SpellValueMod.BasePoint0, (int)GetUnitTargetCountForEffect(effIndex)) } + }); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleEnergize, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 277925 - Shuriken Tornado +class spell_rog_shuriken_tornado : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShurikenStormDamage); + } + + void HandlePeriodicEffect(AuraEffect aurEff) + { + GetTarget().CastSpell(null, SpellIds.ShurikenStormDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandlePeriodicEffect, 0, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 193315 - Sinister Strike +class spell_rog_sinister_strike : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.T5_2PSetBonus); + } + + void HandleDummy(uint effIndex) + { + int damagePerCombo = GetHitDamage(); + AuraEffect t5 = GetCaster().GetAuraEffect(SpellIds.T5_2PSetBonus, 0); + if (t5 != null) + damagePerCombo += t5.GetAmount(); + + int finalDamage = damagePerCombo; + var comboPointCost = GetSpell().GetPowerTypeCostAmount(PowerType.ComboPoints); + if (comboPointCost.HasValue) + finalDamage *= comboPointCost.Value; + + SetHitDamage(finalDamage); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 2, SpellEffectName.Dummy)); + } +} + +[Script] // Called by 1856 - Vanish +class spell_rog_soothing_darkness : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SoothingDarknessTalent, SpellIds.SoothingDarknessHeal); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.SoothingDarknessTalent); + } + + void Heal() + { + GetCaster().CastSpell(GetCaster(), SpellIds.SoothingDarknessHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(Heal)); + } +} + +[Script] // 1784 - Stealth +class spell_rog_stealth : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Sanctuary, SpellIds.StealthStealthAura, SpellIds.StealthShapeshiftAura); + } + + void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + + target.CastSpell(target, SpellIds.Sanctuary, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + target.CastSpell(target, SpellIds.StealthStealthAura, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + target.CastSpell(target, SpellIds.StealthShapeshiftAura, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + + target.RemoveAurasDueToSpell(SpellIds.StealthStealthAura); + target.RemoveAurasDueToSpell(SpellIds.StealthShapeshiftAura); + } + + public override void Register() + { + AfterEffectApply.Add(new(HandleEffectApply, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(HandleEffectRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 212283 - Symbols of Death +class spell_rog_symbols_of_death : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SymbolsOfDeathRANK2, SpellIds.SymbolsOfDeathCritAura); + } + + void HandleEffectHitTarget(uint effIndex) + { + if (GetCaster().HasAura(SpellIds.SymbolsOfDeathRANK2)) + GetCaster().CastSpell(GetCaster(), SpellIds.SymbolsOfDeathCritAura, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.ApplyAura)); + } +} + +[Script] // 57934 - Tricks of the Trade +class spell_rog_tricks_of_the_trade_aura : AuraScript +{ + ObjectGuid _redirectTarget; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TricksOfTheTradeProc); + } + + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Default || !GetTarget().HasAura(SpellIds.TricksOfTheTradeProc)) GetTarget().GetThreatManager().UnregisterRedirectThreat(SpellIds.TricksOfTheTrade); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } } - [Script] // 198020 - Turn the Tables (PvP Talent) - class spell_rog_turn_the_tables : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - bool CheckForStun(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetProcSpell() != null && eventInfo.GetProcSpell().GetSpellInfo().HasAura(AuraType.ModStun); - } + PreventDefaultAction(); - public override void Register() - { - DoCheckEffectProc.Add(new(CheckForStun, 0, AuraType.ProcTriggerSpell)); - } + Unit rogue = GetTarget(); + if (Global.ObjAccessor.GetUnit(rogue, _redirectTarget) != null) + rogue.CastSpell(rogue, SpellIds.TricksOfTheTradeProc, aurEff); + Remove(AuraRemoveMode.Default); } - [Script] // 198023 - Turn the Tables (periodic) - class spell_rog_turn_the_tables_periodic_check : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.TurnTheTablesBuff); - } + AfterEffectRemove.Add(new(OnRemove, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } - void CheckForStun(AuraEffect aurEff) + public void SetRedirectTarget(ObjectGuid guid) { _redirectTarget = guid; } +} + +[Script] // 57934 - Tricks of the Trade +class spell_rog_tricks_of_the_trade : SpellScript +{ + void DoAfterHit() + { + Aura aura = GetHitAura(); + if (aura != null) { - Unit target = GetTarget(); - if (!target.HasAuraType(AuraType.ModStun)) + spell_rog_tricks_of_the_trade_aura script = aura.GetScript(); + if (script != null) { - target.CastSpell(target, SpellIds.TurnTheTablesBuff, aurEff); - PreventDefaultAction(); - Remove(); + Unit explTarget = GetExplTargetUnit(); + if (explTarget != null) + script.SetRedirectTarget(explTarget.GetGUID()); + else + script.SetRedirectTarget(ObjectGuid.Empty); } } - - public override void Register() - { - OnEffectPeriodic.Add(new(CheckForStun, 0, AuraType.PeriodicDummy)); - } } - [Script] // 1856 - Vanish - SpellIds.Vanish - class spell_rog_vanish : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.VanishAura, SpellIds.StealthShapeshiftAura); - } - - void OnLaunchTarget(uint effIndex) - { - PreventHitDefaultEffect(effIndex); - - Unit target = GetHitUnit(); - - target.RemoveAurasByType(AuraType.ModStalked); - if (!target.IsPlayer()) - return; - - if (target.HasAura(SpellIds.VanishAura)) - return; - - target.CastSpell(target, SpellIds.VanishAura, TriggerCastFlags.FullMask); - target.CastSpell(target, SpellIds.StealthShapeshiftAura, TriggerCastFlags.FullMask); - } - - public override void Register() - { - OnEffectLaunchTarget.Add(new(OnLaunchTarget, 1, SpellEffectName.TriggerSpell)); - } + AfterHit.Add(new(DoAfterHit)); } +} - [Script] // 11327 - Vanish - class spell_rog_vanish_AuraScript : AuraScript +[Script] // 59628 - Tricks of the Trade (Proc) +class spell_rog_tricks_of_the_trade_proc : AuraScript +{ + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Stealth); - } - - void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().CastSpell(GetTarget(), SpellIds.Stealth, TriggerCastFlags.FullMask); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); - } + GetTarget().GetThreatManager().UnregisterRedirectThreat(SpellIds.TricksOfTheTrade); } - [Script] // 79134 - Venomous Wounds - SpellIds.VenomousWounds - class spell_rog_venomous_wounds : AuraScript + public override void Register() { - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - int extraEnergy = aurEff.GetAmount(); - GetTarget().ModifyPower(PowerType.Energy, extraEnergy); - } + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - public override void Register() +[Script] // 198020 - Turn the Tables (PvP Talent) +class spell_rog_turn_the_tables : AuraScript +{ + bool CheckForStun(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetProcSpell() != null && eventInfo.GetProcSpell().GetSpellInfo().HasAura(AuraType.ModStun); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckForStun, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 198023 - Turn the Tables (periodic) +class spell_rog_turn_the_tables_periodic_check : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TurnTheTablesBuff); + } + + void CheckForStun(AuraEffect aurEff) + { + Unit target = GetTarget(); + if (!target.HasAuraType(AuraType.ModStun)) { - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + target.CastSpell(target, SpellIds.TurnTheTablesBuff, aurEff); + PreventDefaultAction(); + Remove(); } } -} \ No newline at end of file + + public override void Register() + { + OnEffectPeriodic.Add(new(CheckForStun, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 1856 - Vanish - SpellIds.Vanish +class spell_rog_vanish : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VanishAura, SpellIds.StealthShapeshiftAura); + } + + void OnLaunchTarget(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + + Unit target = GetHitUnit(); + + target.RemoveAurasByType(AuraType.ModStalked); + if (!target.IsPlayer()) + return; + + if (target.HasAura(SpellIds.VanishAura)) + return; + + target.CastSpell(target, SpellIds.VanishAura, TriggerCastFlags.FullMask); + target.CastSpell(target, SpellIds.StealthShapeshiftAura, TriggerCastFlags.FullMask); + } + + public override void Register() + { + OnEffectLaunchTarget.Add(new(OnLaunchTarget, 1, SpellEffectName.TriggerSpell)); + } +} + +[Script] // 11327 - Vanish +class spell_rog_vanish_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Stealth); + } + + void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetTarget().CastSpell(GetTarget(), SpellIds.Stealth, TriggerCastFlags.FullMask); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 79134 - Venomous Wounds +class spell_rog_venomous_wounds : AuraScript +{ + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + int extraEnergy = aurEff.GetAmount(); + GetTarget().ModifyPower(PowerType.Energy, extraEnergy); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} diff --git a/Source/Scripts/Spells/Shaman.cs b/Source/Scripts/Spells/Shaman.cs index cbc6ea2e8..ad36bd139 100644 --- a/Source/Scripts/Spells/Shaman.cs +++ b/Source/Scripts/Spells/Shaman.cs @@ -1,1909 +1,3484 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Framework.Dynamic; using Game.AI; using Game.Entities; +using Game.Maps; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; +using System.Linq; -using static Global; +namespace Scripts.Spells.Shaman; -namespace Scripts.Spells.Shaman +struct SpellIds { + public const uint AftershockEnergize = 210712; + public const uint AncestralGuidance = 108281; + public const uint AncestralGuidanceHeal = 114911; + public const uint ArcticSnowstormAreatrigger = 462767; + public const uint ArcticSnowstormSlow = 462765; + public const uint AscendanceElemental = 114050; + public const uint AscendanceEnhancement = 114051; + public const uint AscendanceRestoration = 114052; + public const uint ChainLightning = 188443; + public const uint ChainLightningEnergize = 195897; + public const uint ChainLightningOverload = 45297; + public const uint ChainLightningOverloadEnergize = 218558; + public const uint ChainedHeal = 70809; + public const uint ConvergingStorms = 384363; + public const uint CrashLightning = 187874; + public const uint CrashLightningCleave = 187878; + public const uint CrashLightningDamageBuff = 333964; + public const uint DelugeAura = 200075; + public const uint DelugeTalent = 200076; + public const uint DoomWindsDamage = 469270; + public const uint DoomWindsLegendaryCooldown = 335904; + public const uint Earthquake = 61882; + public const uint EarthquakeKnockingDown = 77505; + public const uint EarthquakeTick = 77478; + public const uint EarthShieldHeal = 204290; + public const uint EarthenRagePassive = 170374; + public const uint EarthenRagePeriodic = 170377; + public const uint EarthenRageDamage = 170379; + public const uint EchoesOfGreatSunderingLegendary = 336217; + public const uint EchoesOfGreatSunderingTalent = 384088; + public const uint Electrified = 64930; + public const uint ElementalBlast = 117014; + public const uint ElementalBlastCrit = 118522; + public const uint ElementalBlastHaste = 173183; + public const uint ElementalBlastMastery = 173184; + public const uint ElementalBlastOverload = 120588; + public const uint ElementalMastery = 16166; + public const uint ElementalWeaponsBuff = 408390; + public const uint EnergySurge = 40465; + public const uint EnhancedElements = 77223; + public const uint FireNovaDamage = 333977; + public const uint FireNovaEnabler = 466622; + public const uint FlameShock = 188389; + public const uint FlametongueAttack = 10444; + public const uint FlametongueWeaponEnchant = 334294; + public const uint FlametongueWeaponAura = 319778; + public const uint ForcefulWindsProc = 262652; + public const uint ForcefulWindsTalent = 262647; + public const uint FrostShock = 196840; + public const uint FrostShockEnergize = 289439; + public const uint GatheringStorms = 198299; + public const uint GatheringStormsBuff = 198300; + public const uint GhostWolf = 2645; + public const uint HailstormBuff = 334196; + public const uint HailstormTalent = 334195; + public const uint HealingRainVisual = 147490; + public const uint HealingRain = 73920; + public const uint HealingRainHeal = 73921; + public const uint IceStrikeOverrideAura = 466469; + public const uint IceStrikeProc = 466467; + public const uint Icefury = 210714; + public const uint IcefuryOverload = 219271; + public const uint IgneousPotential = 279830; + public const uint ItemLightningShield = 23552; + public const uint ItemLightningShieldDamage = 27635; + public const uint ItemManaSurge = 23571; + public const uint LavaBurst = 51505; + public const uint LavaBurstBonusDamage = 71824; + public const uint LavaBurstOverload = 77451; + public const uint LavaLash = 60103; + public const uint LavaSurge = 77762; + public const uint LightningBolt = 188196; + public const uint LightningBoltEnergize = 214815; + public const uint LightningBoltOverload = 45284; + public const uint LightningBoltOverloadEnergize = 214816; + public const uint LiquidMagmaHit = 192231; + public const uint MaelstromController = 343725; + public const uint MaelstromWeaponModAura = 187881; + public const uint MaelstromWeaponVisibleAura = 344179; + public const uint MaelstromWeaponOverlay = 187890; + public const uint MaelstromWeaponOverlayHeals = 412692; + public const uint MasteryElementalOverload = 168534; + public const uint MoltenAssault = 334033; + public const uint MoltenThunderProc = 469346; + public const uint MoltenThunderTalent = 469344; + public const uint NaturesGuardianCooldown = 445698; + public const uint OverflowingMaelstromAura = 384669; + public const uint OverflowingMaelstromTalent = 384149; + public const uint PathOfFlamesSpread = 210621; + public const uint PathOfFlamesTalent = 201909; + public const uint PowerSurge = 40466; + public const uint PrimordialWaveDamage = 375984; + public const uint RestorativeMists = 114083; + public const uint RestorativeMistsInitial = 294020; + public const uint Riptide = 61295; + public const uint SpiritWolfTalent = 260878; + public const uint SpiritWolfPeriodic = 260882; + public const uint SpiritWolfAura = 260881; + public const uint StormblastDamage = 390287; + public const uint StormblastProc = 470466; + public const uint StormblastTalent = 319930; + public const uint Stormflurry = 344357; + public const uint StormflurryArtifact = 198367; + public const uint Stormkeeper = 191634; + public const uint Stormstrike = 17364; + public const uint StormstrikeDamageMainHand = 32175; + public const uint StormstrikeDamageOffHand = 32176; + public const uint StormsurgeProc = 201846; + public const uint StormweaverPvpTalent = 410673; + public const uint StormweaverPvpTalentBuff = 410681; + public const uint T29_2PElementalDamageBuff = 394651; + public const uint ThorimsInvocation = 384444; + public const uint TidalWaves = 53390; + public const uint TotemicPowerArmor = 28827; + public const uint TotemicPowerAttackPower = 28826; + public const uint TotemicPowerMP5 = 28824; + public const uint TotemicPowerSpellPower = 28825; + public const uint UndulationProc = 216251; + public const uint UnlimitedPowerBuff = 272737; + public const uint UnrelentingStormsReduction = 470491; + public const uint UnrelentingStormsTalent = 470490; + public const uint UnrulyWinds = 390288; + public const uint VoltaicBlazeDamage = 470057; + public const uint VoltaicBlazeOverride = 470058; + public const uint WindfuryAttack = 25504; + public const uint WindfuryAura = 319773; + public const uint WindfuryEnchantment = 334302; + public const uint WindfuryVisual1 = 466440; + public const uint WindfuryVisual2 = 466442; + public const uint WindfuryVisual3 = 466443; + public const uint WindRush = 192082; + public const uint WindstrikeDamageMainHand = 115357; + public const uint WindstrikeDamageOffHand = 115360; - struct SpellIds + + public const uint LabelShamanWindfuryTotem = 1038; +} + +class spell_sha_maelstrom_weapon_base +{ + public static bool Validate() { - public const uint AftershockEnergize = 210712; - public const uint AncestralGuidance = 108281; - public const uint AncestralGuidanceHeal = 114911; - public const uint AscendanceElemental = 114050; - public const uint AscendanceEnhancement = 114051; - public const uint AscendanceRestoration = 114052; - public const uint ChainLightning = 188443; - public const uint ChainLightningEnergize = 195897; - public const uint ChainLightningOverload = 45297; - public const uint ChainLightningOverloadEnergize = 218558; - public const uint ChainedHeal = 70809; - public const uint CrashLightningCleave = 187878; - public const uint DoomWindsLegendaryCooldown = 335904; - public const uint Earthquake = 61882; - public const uint EarthquakeKnockingDown = 77505; - public const uint EarthquakeTick = 77478; - public const uint EarthShieldHeal = 204290; - public const uint EarthenRagePassive = 170374; - public const uint EarthenRagePeriodic = 170377; - public const uint EarthenRageDamage = 170379; - public const uint EchoesOfGreatSunderingLegendary = 336217; - public const uint EchoesOfGreatSunderingTalent = 384088; - public const uint Electrified = 64930; - public const uint ElementalBlast = 117014; - public const uint ElementalBlastCrit = 118522; - public const uint ElementalBlastEnergize = 344645; - public const uint ElementalBlastHaste = 173183; - public const uint ElementalBlastMastery = 173184; - public const uint ElementalBlastOverload = 120588; - public const uint ElementalMastery = 16166; - public const uint EnergySurge = 40465; - public const uint FlameShock = 188389; - public const uint FlametongueAttack = 10444; - public const uint FlametongueWeaponEnchant = 334294; - public const uint FlametongueWeaponAura = 319778; - public const uint FrostShockEnergize = 289439; - public const uint GatheringStorms = 198299; - public const uint GatheringStormsBuff = 198300; - public const uint GhostWolf = 2645; - public const uint HealingRainVisual = 147490; - public const uint HealingRainHeal = 73921; - public const uint Icefury = 210714; - public const uint IcefuryOverload = 219271; - public const uint IgneousPotential = 279830; - public const uint ItemLightningShield = 23552; - public const uint ItemLightningShieldDamage = 27635; - public const uint ItemManaSurge = 23571; - public const uint LavaBeam = 114074; - public const uint LavaBeamOverload = 114738; - public const uint LavaBurst = 51505; - public const uint LavaBurstBonusDamage = 71824; - public const uint LavaBurstOverload = 77451; - public const uint LavaSurge = 77762; - public const uint LightningBolt = 188196; - public const uint LightningBoltEnergize = 214815; - public const uint LightningBoltOverload = 45284; - public const uint LightningBoltOverloadEnergize = 214816; - public const uint LiquidMagmaHit = 192231; - public const uint MaelstromController = 343725; - public const uint MasteryElementalOverload = 168534; - public const uint PathOfFlamesSpread = 210621; - public const uint PathOfFlamesTalent = 201909; - public const uint PowerSurge = 40466; - public const uint RestorativeMists = 114083; - public const uint RestorativeMistsInitial = 294020; - public const uint Riptide = 61295; - public const uint SpiritWolfTalent = 260878; - public const uint SpiritWolfPeriodic = 260882; - public const uint SpiritWolfAura = 260881; - public const uint Stormkeeper = 191634; - public const uint Stormstrike = 17364; - public const uint T292PElementalDamageBuff = 394651; - public const uint TidalWaves = 53390; - public const uint TotemicPowerArmor = 28827; - public const uint TotemicPowerAttackPower = 28826; - public const uint TotemicPowerMp5 = 28824; - public const uint TotemicPowerSpellPower = 28825; - public const uint UndulationProc = 216251; - public const uint UnlimitedPowerBuff = 272737; - public const uint VolcanicSurge = 408572; - public const uint WindfuryAttack = 25504; - public const uint WindfuryEnchantment = 334302; - public const uint WindRush = 192082; - - public const uint LabelShamanWindfuryTotem = 1038; + return SpellScriptBase.ValidateSpellInfo + (SpellIds.MaelstromWeaponVisibleAura, + SpellIds.MaelstromWeaponOverlay, + SpellIds.MaelstromWeaponOverlayHeals, + SpellIds.OverflowingMaelstromTalent, + SpellIds.OverflowingMaelstromAura, + SpellIds.StormweaverPvpTalentBuff, + SpellIds.IceStrikeProc, + SpellIds.HailstormBuff, + SpellIds.HailstormTalent) + && SpellScriptBase.ValidateSpellEffect((SpellIds.MaelstromWeaponModAura, 1), (SpellIds.StormweaverPvpTalent, 0)); } - [Script] // 273221 - Aftershock - class spell_sha_aftershock : AuraScript + public static void GenerateMaelstromWeapon(Unit shaman, int stacks) { - public override bool Validate(SpellInfo spellEntry) + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + while (--stacks >= 0) { - return ValidateSpellInfo(SpellIds.AftershockEnergize); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - if (procSpell != null) + uint totalStacks = shaman.GetAuraCount(SpellIds.MaelstromWeaponVisibleAura); + if (totalStacks >= 4) { - var cost = procSpell.GetPowerTypeCostAmount(PowerType.Maelstrom); - if (cost.HasValue) - return cost.Value > 0 && RandomHelper.randChance(aurEff.GetAmount()); + // cast action bar overlays + if (!shaman.HasAura(SpellIds.StormweaverPvpTalent)) + shaman.CastSpell(shaman, SpellIds.MaelstromWeaponOverlayHeals, args); + + shaman.CastSpell(shaman, SpellIds.MaelstromWeaponOverlay, args); } - return false; - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Spell procSpell = eventInfo.GetProcSpell(); - int? energize = procSpell.GetPowerTypeCostAmount(PowerType.Maelstrom); - - eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.AftershockEnergize, new CastSpellExtraArgs(energize.HasValue) - .AddSpellMod(SpellValueMod.BasePoint0, energize.Value)); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + shaman.CastSpell(shaman, SpellIds.MaelstromWeaponModAura, args); + shaman.CastSpell(shaman, SpellIds.MaelstromWeaponVisibleAura, args); + if (totalStacks >= 5 && shaman.HasAura(SpellIds.OverflowingMaelstromTalent)) + shaman.CastSpell(shaman, SpellIds.OverflowingMaelstromAura, args); } } - [Script] // 108281 - Ancestral Guidance - class spell_sha_ancestral_guidance : AuraScript + public static void ConsumeMaelstromWeapon(Unit shaman, Aura maelstromWeaponVisibleAura, int stacks, Spell consumingSpell = null) { - public override bool Validate(SpellInfo spellInfo) + AuraEffect stormweaver = shaman.GetAuraEffect(SpellIds.StormweaverPvpTalent, 0); + if (stormweaver != null) { - return ValidateSpellInfo(SpellIds.AncestralGuidanceHeal); + shaman.RemoveAurasDueToSpell(SpellIds.StormweaverPvpTalentBuff); // remove to ensure new buff has exactly "consumedStacks" stacks + Aura maelstromSpellMod = shaman.GetAura(SpellIds.MaelstromWeaponModAura); + if (maelstromSpellMod != null) + { + shaman.CastSpell(shaman, SpellIds.StormweaverPvpTalentBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = consumingSpell, + SpellValueOverrides = + { + new(SpellValueMod.BasePoint0, maelstromSpellMod.GetEffect(0).GetAmount()), + // this is indeed very silly but it is how it behaves on official servers + // it ignores how many stacks were actually consumed and calculates benefit from max stacks (Thorim's Invocation can consume less stacks than entire aura) + new(SpellValueMod.BasePoint1, MathFunctions.CalculatePct(maelstromSpellMod.GetEffect(1).GetAmount(), stormweaver.GetAmount())), + new(SpellValueMod.AuraStack, Math.Min(stacks, maelstromWeaponVisibleAura.GetStackAmount())) + } + }); + } } - bool CheckProc(ProcEventInfo eventInfo) + Aura iceStrike = shaman.GetAura(SpellIds.IceStrikeProc); + if (iceStrike != null) { - if (eventInfo.GetHealInfo() != null && eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().Id == SpellIds.AncestralGuidanceHeal) - return false; + spell_sha_ice_strike_proc script = iceStrike.GetScript(); + if (script != null) + script.AttemptProc(); + } - if (eventInfo.GetHealInfo() == null && eventInfo.GetDamageInfo() == null) - return false; + if (shaman.HasAura(SpellIds.HailstormTalent)) + shaman.CastSpell(shaman, SpellIds.HailstormBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = consumingSpell, + SpellValueOverrides = { new(SpellValueMod.AuraStack, Math.Min(stacks, maelstromWeaponVisibleAura.GetStackAmount())) } + }); + if (maelstromWeaponVisibleAura.ModStackAmount(-stacks)) + return; + + // not removed + byte newStacks = maelstromWeaponVisibleAura.GetStackAmount(); + + Aura overflowingMaelstrom = shaman.GetAura(SpellIds.OverflowingMaelstromAura); + if (overflowingMaelstrom != null) + { + if (newStacks > 5) + overflowingMaelstrom.SetStackAmount((byte)(newStacks - 5)); + else + overflowingMaelstrom.Remove(); + } + + Aura maelstromSpellMod1 = shaman.GetAura(SpellIds.MaelstromWeaponModAura); + if (maelstromSpellMod1 != null) + { + if (newStacks > 0) + maelstromSpellMod1.SetStackAmount(Math.Min(newStacks, (byte)5)); + else + maelstromSpellMod1.Remove(); + } + + if (newStacks < 5) + { + shaman.RemoveAurasDueToSpell(SpellIds.MaelstromWeaponOverlay); + shaman.RemoveAurasDueToSpell(SpellIds.MaelstromWeaponOverlayHeals); + } + } +} + +class WindfuryProcEvent : BasicEvent +{ + Unit _shaman; + CastSpellTargetArg _target; + int _index; + int _endIndex; + + class WindfuryProcEventInfo + { + public TimeSpan Delay; + public uint VisualSpellId; + } + + static WindfuryProcEventInfo[] Sequence = + { + new WindfuryProcEventInfo() { Delay = TimeSpan.FromSeconds(500), VisualSpellId = SpellIds.WindfuryVisual1 }, + new WindfuryProcEventInfo() { Delay = TimeSpan.FromSeconds(150), VisualSpellId = SpellIds.WindfuryVisual2 }, + new WindfuryProcEventInfo() { Delay = TimeSpan.FromSeconds(250), VisualSpellId = SpellIds.WindfuryVisual3 }, + }; + + public WindfuryProcEvent(Unit shaman, Unit target, int attacks) + { + _shaman = shaman; + _target = target; + _index = 0; + _endIndex = attacks; + } + + public override bool Execute(ulong time, uint diff) + { + if (_target.Targets == null) return true; - } - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + _target.Targets.Update(_shaman); + if (_target.Targets.GetUnitTarget() == null) + return true; + + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError; + args.TriggeringAura = _shaman.GetAuraEffect(SpellIds.WindfuryAura, 0); // prevent proc from itself + + _shaman.CastSpell(_shaman, Sequence[_index].VisualSpellId, args); + _shaman.CastSpell(_target, SpellIds.WindfuryAttack, args); + + if (++_index == _endIndex) + return true; + + _shaman.m_Events.AddEvent(this, TimeSpan.FromSeconds(time) + Sequence[_index].Delay); + return false; + } + + public static void Trigger(Unit shaman, Unit target) + { + // Not a separate script because of ordering requirements for Forceful Winds + if (shaman.HasAuraEffect(SpellIds.ForcefulWindsTalent, 0)) { - PreventDefaultAction(); - int bp0 = MathFunctions.CalculatePct((int)(eventInfo.GetDamageInfo() != null ? eventInfo.GetDamageInfo().GetDamage() : eventInfo.GetHealInfo().GetHeal()), aurEff.GetAmount()); - if (bp0 != 0) + Aura forcefulWinds = shaman.GetAura(SpellIds.ForcefulWindsProc); + if (forcefulWinds != null) { - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, bp0); - eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.AncestralGuidanceHeal, args); + // gaining a stack should not refresh duration + uint maxStack = forcefulWinds.CalcMaxStackAmount(); + if (forcefulWinds.GetStackAmount() < maxStack) + forcefulWinds.SetStackAmount((byte)(forcefulWinds.GetStackAmount() + 1)); + } + else + { + shaman.CastSpell(shaman, SpellIds.ForcefulWindsProc, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); } } - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.PeriodicDummy)); - } + int attacks = 2; + AuraEffect unrulyWinds = shaman.GetAuraEffect(SpellIds.UnrulyWinds, 0); RandomHelper.randChance(unrulyWinds.GetAmount()); + if (unrulyWinds != null) + ++attacks; + + shaman.m_Events.AddEventAtOffset(new WindfuryProcEvent(shaman, target, attacks), Sequence.First().Delay); + } +} + +[Script] // 273221 - Aftershock +class spell_sha_aftershock : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AftershockEnergize); } - [Script] // 114911 - Ancestral Guidance Heal - class spell_sha_ancestral_guidance_heal : SpellScript + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell != null) { - return ValidateSpellInfo(SpellIds.AncestralGuidance); + var cost = procSpell.GetPowerTypeCostAmount(PowerType.Maelstrom); + if (cost.HasValue) + return cost > 0 && RandomHelper.randChance(aurEff.GetAmount()); } - void ResizeTargets(List targets) - { - SelectRandomInjuredTargets(targets, 3, true); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(ResizeTargets, 0, Targets.UnitDestAreaAlly)); - } + return false; } - [Script] // 114052 - Ascendance (Restoration) - class spell_sha_ascendance_restoration : AuraScript + static void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - uint _healToDistribute; - - public override bool Validate(SpellInfo spellInfo) + Spell procSpell = eventInfo.GetProcSpell(); + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.AftershockEnergize, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.RestorativeMists); - } - - bool CheckProc(ProcEventInfo procInfo) - { - return procInfo.GetHealInfo() != null && procInfo.GetHealInfo().GetOriginalHeal() != 0 && procInfo.GetSpellInfo().Id != SpellIds.RestorativeMistsInitial; - } - - void OnProcHeal(AuraEffect aurEff, ProcEventInfo procInfo) - { - _healToDistribute += procInfo.GetHealInfo().GetOriginalHeal(); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - if (_healToDistribute == 0) - return; - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, (int)_healToDistribute); - GetTarget().CastSpell(null, SpellIds.RestorativeMists, args); - _healToDistribute = 0; - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(OnProcHeal, 1, AuraType.PeriodicDummy)); - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 1, AuraType.PeriodicDummy)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = procSpell, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, procSpell.GetPowerTypeCostAmount(PowerType.Maelstrom).Value) } + }); } - [Script] // 188443 - Chain Lightning - class spell_sha_chain_lightning : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 108281 - Ancestral Guidance +class spell_sha_ancestral_guidance : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AncestralGuidanceHeal); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetSpellInfo() != null && eventInfo.GetSpellInfo().Id == SpellIds.AncestralGuidanceHeal) + return false; + + if (eventInfo.GetHealInfo() == null && eventInfo.GetDamageInfo() == null) + return false; + + return true; + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + int bp0 = MathFunctions.CalculatePct((int)(eventInfo.GetDamageInfo() != null ? eventInfo.GetDamageInfo().GetDamage() : eventInfo.GetHealInfo().GetHeal()), aurEff.GetAmount()); + if (bp0 == 0) + return; + + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.AncestralGuidanceHeal, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.ChainLightningEnergize, SpellIds.MaelstromController) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, bp0) } + }); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 114911 - Ancestral Guidance Heal +class spell_sha_ancestral_guidance_heal : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.AncestralGuidance); + } + + void ResizeTargets(List targets) + { + SelectRandomInjuredTargets(targets, 3, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(ResizeTargets, 0, Targets.UnitCasterAreaRaid)); + } +} + +[Script] // 462764 - Arctic Snowstorm +class spell_sha_arctic_snowstorm : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ArcticSnowstormAreatrigger); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.ArcticSnowstormAreatrigger, + new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 198299 - Gathering Storms +class spell_sha_artifact_gathering_storms : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GatheringStorms, SpellIds.GatheringStormsBuff); + } + + public override bool Load() + { + return GetCaster().HasAuraEffect(SpellIds.GatheringStorms, 0); + } + + void TriggerBuff(uint effIndex) + { + AuraEffect gatheringStorms = GetCaster().GetAuraEffect(SpellIds.GatheringStorms, 0); + if (gatheringStorms == null) + return; + + GetCaster().CastSpell(GetCaster(), SpellIds.GatheringStormsBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, (int)(gatheringStorms.GetAmount() * GetUnitTargetCountForEffect(effIndex))) } + }); + } + + public override void Register() + { + OnEffectHit.Add(new(TriggerBuff, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 114052 - Ascendance (Restoration) +class spell_sha_ascendance_restoration : AuraScript +{ + int _healToDistribute; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RestorativeMists); + } + + static bool CheckProc(ProcEventInfo procInfo) + { + return procInfo.GetHealInfo() != null && procInfo.GetHealInfo().GetOriginalHeal() != 0 && procInfo.GetSpellInfo().Id != SpellIds.RestorativeMistsInitial; + } + + void OnProcHeal(AuraEffect aurEff, ProcEventInfo procInfo) + { + _healToDistribute += MathFunctions.CalculatePct((int)(procInfo.GetHealInfo().GetOriginalHeal()), aurEff.GetAmount()); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + if (_healToDistribute == 0) + return; + + GetTarget().CastSpell(null, SpellIds.RestorativeMists, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, _healToDistribute) } + }); + _healToDistribute = 0; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(OnProcHeal, 8, AuraType.Dummy)); + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 6, AuraType.PeriodicDummy)); + } +} + +[Script] // 390370 - Ashen Catalyst +class spell_sha_ashen_catalyst : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LavaLash); + } + + void ReduceLavaLashCooldown(AuraEffect aurEff, ProcEventInfo procInfo) + { + GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.LavaLash, -aurEff.GetAmount() * TimeSpan.FromSeconds(100)); + } + + public override void Register() + { + OnEffectProc.Add(new(ReduceLavaLashCooldown, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 188443 - Chain Lightning +class spell_sha_chain_lightning_crash_lightning : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CrashLightning, SpellIds.CrashLightningDamageBuff); + } + + public override bool Load() + { + return GetCaster().HasSpell(SpellIds.CrashLightning); + } + + void HandleCooldownReduction(uint effIndex) + { + GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.CrashLightning, TimeSpan.FromSeconds(-GetEffectValue()) * GetUnitTargetCountForEffect(0)); + } + + void HandleDamageBuff(uint effIndex) + { + long targetsHit = GetUnitTargetCountForEffect(effIndex); + if (targetsHit > 1) + GetCaster().CastSpell(GetCaster(), SpellIds.CrashLightningDamageBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.AuraStack, (int)targetsHit) } + }); + } + + public override void Register() + { + OnEffectLaunch.Add(new(HandleCooldownReduction, 2, SpellEffectName.Dummy)); + OnEffectLaunch.Add(new(HandleDamageBuff, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 188443 - Chain Lightning +class spell_sha_chain_lightning_energize : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChainLightningEnergize) && ValidateSpellEffect((SpellIds.MaelstromController, 4)); - } - - void HandleScript(uint effIndex) - { - AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 4); - if (energizeAmount != null) - GetCaster().CastSpell(GetCaster(), SpellIds.ChainLightningEnergize, new CastSpellExtraArgs(energizeAmount) - .AddSpellMod(SpellValueMod.BasePoint0, (int)(energizeAmount.GetAmount() * GetUnitTargetCountForEffect(0)))); - } - - public override void Register() - { - OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); - } } - [Script] // 45297 - Chain Lightning Overload - class spell_sha_chain_lightning_overload : SpellScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ChainLightningOverloadEnergize, SpellIds.MaelstromController) - && ValidateSpellEffect((SpellIds.MaelstromController, 5)); - } - - void HandleScript(uint effIndex) - { - AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 5); - if (energizeAmount != null) - GetCaster().CastSpell(GetCaster(), SpellIds.ChainLightningOverloadEnergize, new CastSpellExtraArgs(energizeAmount) - .AddSpellMod(SpellValueMod.BasePoint0, (int)(energizeAmount.GetAmount() * GetUnitTargetCountForEffect(0)))); - } - - public override void Register() - { - OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); - } + return GetCaster().HasAuraEffect(SpellIds.MaelstromController, 4); } - [Script] // 187874 - Crash Lightning - class spell_sha_crash_lightning : SpellScript + void HandleScript(uint effIndex) { - int _targetsHit; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CrashLightningCleave, SpellIds.GatheringStorms, SpellIds.GatheringStormsBuff); - } - - void CountTargets(List targets) - { - _targetsHit = targets.Count; - } - - void TriggerCleaveBuff() - { - if (_targetsHit >= 2) - GetCaster().CastSpell(GetCaster(), SpellIds.CrashLightningCleave, true); - - AuraEffect gatheringStorms = GetCaster().GetAuraEffect(SpellIds.GatheringStorms, 0); - if (gatheringStorms != null) + AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 4); + if (energizeAmount != null) + GetCaster().CastSpell(GetCaster(), SpellIds.ChainLightningEnergize, new CastSpellExtraArgs() { - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, gatheringStorms.GetAmount() * _targetsHit); - GetCaster().CastSpell(GetCaster(), SpellIds.GatheringStormsBuff, args); - } - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(CountTargets, 0, Targets.UnitConeCasterToDestEnemy)); - AfterCast.Add(new(TriggerCleaveBuff)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = energizeAmount, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, (int)(energizeAmount.GetAmount() * GetUnitTargetCountForEffect(0))) } + }); } - [Script] // 378270 - Deeply Rooted Elements - class spell_sha_deeply_rooted_elements : AuraScript + public override void Register() { - uint requiredSpellId; - uint ascendanceSpellId; - int _procAttempts; + OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); + } +} - public override bool Validate(SpellInfo spellInfo) +[Script] // 45297 - Chain Lightning Overload +class spell_sha_chain_lightning_overload : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChainLightningOverloadEnergize) + && ValidateSpellEffect((SpellIds.MaelstromController, 5)); + } + + public override bool Load() + { + return GetCaster().HasAuraEffect(SpellIds.MaelstromController, 5); + } + + void HandleScript(uint effIndex) + { + AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 5); + if (energizeAmount != null) + GetCaster().CastSpell(GetCaster(), SpellIds.ChainLightningOverloadEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = energizeAmount, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, (int)(energizeAmount.GetAmount() * GetUnitTargetCountForEffect(0))) } + }); + } + + public override void Register() + { + OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 384363 - Converging Storms +class spell_sha_converging_storms : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ConvergingStorms, SpellIds.GatheringStormsBuff); + } + + public override bool Load() + { + return GetCaster().HasAuraEffect(SpellIds.ConvergingStorms, 0); + } + + void TriggerBuff(uint effIndex) + { + AuraEffect convergingStorms = GetCaster().GetAuraEffect(SpellIds.ConvergingStorms, 0); + if (convergingStorms == null) + return; + + GetCaster().CastSpell(GetCaster(), SpellIds.GatheringStormsBuff, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.LavaBurst, SpellIds.Stormstrike, SpellIds.Riptide, SpellIds.AscendanceElemental, SpellIds.AscendanceEnhancement, SpellIds.AscendanceRestoration) + TriggerFlags = TriggerCastFlags.FullMask, + SpellValueOverrides = { new(SpellValueMod.AuraStack, (int)Math.Min(GetUnitTargetCountForEffect(effIndex), 6)) } + }); + } + + public override void Register() + { + OnEffectHit.Add(new(TriggerBuff, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script("spell_sha_stormsurge_proc")] +[Script("spell_sha_converging_storms_buff")] // 198300 - Converging Storms +class spell_sha_delayed_stormstrike_mod_charge_drop_proc : AuraScript +{ + void DropAura(ProcEventInfo eventInfo) + { + GetAura().DropChargeDelayed(1); + } + + public override void Register() + { + AfterProc.Add(new(DropAura)); + } +} + +[Script] // 187874 - Crash Lightning +class spell_sha_crash_lightning : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CrashLightningCleave); + } + + void TriggerCleaveBuff(uint effIndex) + { + if (GetUnitTargetCountForEffect(effIndex) >= 2) + GetCaster().CastSpell(GetCaster(), SpellIds.CrashLightningCleave, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHit.Add(new(TriggerCleaveBuff, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 200076 - Deluge (attached to 77472 - Healing Wave, 8004 - Healing Surge and 1064 - Chain Heal +class spell_sha_deluge : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Riptide, SpellIds.DelugeAura) + && ValidateSpellEffect((SpellIds.DelugeTalent, 0)); + } + + void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod) + { + AuraEffect deluge = GetCaster().GetAuraEffect(SpellIds.DelugeTalent, 0); + if (deluge != null) + if (victim.GetAura(SpellIds.Riptide, GetCaster().GetGUID()) != null || victim.GetAura(SpellIds.DelugeAura, GetCaster().GetGUID()) != null) + MathFunctions.AddPct(ref pctMod, deluge.GetAmount()); + } + + public override void Register() + { + CalcHealing.Add(new(CalculateHealingBonus)); + } +} + +[Script] // 200075 - Deluge (attached to 73920 - Healing Rain) +class spell_sha_deluge_healing_rain : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DelugeTalent, SpellIds.DelugeAura); + } + + public override bool Load() + { + return GetUnitOwner().HasAura(SpellIds.DelugeTalent); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + GetCaster().CastSpell(GetHealingRainPosition(GetAura()), SpellIds.DelugeAura, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + } + + Position GetHealingRainPosition(Aura healingRain) + { + spell_sha_healing_rain_aura script = healingRain.GetScript(); + if (script != null) + return script.GetPosition(); + + return healingRain.GetUnitOwner().GetPosition(); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 1, AuraType.PeriodicDummy)); + } +} + +[Script] // 378270 - Deeply Rooted Elements +class spell_sha_deeply_rooted_elements : AuraScript +{ + int _procAttempts; + uint _triggeringSpellId; + uint _triggeredSpellId; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LavaBurst, SpellIds.Stormstrike, SpellIds.Riptide, + SpellIds.AscendanceElemental, SpellIds.AscendanceEnhancement, SpellIds.AscendanceRestoration) && ValidateSpellEffect((spellInfo.Id, 0)) && spellInfo.GetEffect(0).IsAura(); - } - - public override bool Load() - { - return GetUnitOwner().IsPlayer(); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - if (procInfo.GetSpellInfo() == null) - return false; - - if (procInfo.GetSpellInfo().Id != requiredSpellId) - return false; - - return RandomHelper.randChance(_procAttempts++ - 2); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - _procAttempts = 0; - - Unit target = eventInfo.GetActor(); - - int duration = GetEffect(0).GetAmount(); - Aura ascendanceAura = target.GetAura(ascendanceSpellId); - if (ascendanceAura != null) - duration += ascendanceAura.GetDuration(); - - target.CastSpell(target, ascendanceSpellId, - new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnoreCastInProgress) - .SetTriggeringAura(aurEff) - .SetTriggeringSpell(eventInfo.GetProcSpell()) - .AddSpellMod(SpellValueMod.Duration, duration)); - } - - public override void Register() - { - if (GetAura() == null || GetUnitOwner().ToPlayer().GetPrimarySpecialization() == ChrSpecialization.ShamanElemental) - { - requiredSpellId = SpellIds.LavaBurst; - ascendanceSpellId = SpellIds.AscendanceElemental; - DoCheckEffectProc.Add(new(CheckProc, 1, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - - if (GetAura() == null || GetUnitOwner().ToPlayer().GetPrimarySpecialization() == ChrSpecialization.ShamanEnhancement) - { - requiredSpellId = SpellIds.Stormstrike; - ascendanceSpellId = SpellIds.AscendanceEnhancement; - DoCheckEffectProc.Add(new(CheckProc, 2, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 2, AuraType.Dummy)); - } - - if (GetAura() == null || GetUnitOwner().ToPlayer().GetPrimarySpecialization() == ChrSpecialization.ShamanRestoration) - { - requiredSpellId = SpellIds.Riptide; - ascendanceSpellId = SpellIds.AscendanceRestoration; - DoCheckEffectProc.Add(new(CheckProc, 3, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 3, AuraType.Dummy)); - } - } } - [Script] // 335902 - Doom Winds - class spell_sha_doom_winds_legendary : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DoomWindsLegendaryCooldown); - } - - bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - if (GetTarget().HasAura(SpellIds.DoomWindsLegendaryCooldown)) - return false; - - SpellInfo spellInfo = procInfo.GetSpellInfo(); - if (spellInfo == null) - return false; - - return spellInfo.HasLabel(SpellIds.LabelShamanWindfuryTotem); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } + return GetUnitOwner().IsPlayer(); } - [Script] // 207778 - Downpour - class spell_sha_downpour : SpellScript + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) { - int _healedTargets; + if (procInfo.GetSpellInfo() == null) + return false; - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1)); - } + if (procInfo.GetSpellInfo().Id != _triggeringSpellId) + return false; - void FilterTargets(List targets) - { - SelectRandomInjuredTargets(targets, 6, true); - } - - void CountEffectivelyHealedTarget() - { - // Cooldown increased for each target effectively healed - if (GetHitHeal() != 0) - ++_healedTargets; - } - - void HandleCooldown() - { - var cooldown = TimeSpan.FromMilliseconds(GetSpellInfo().RecoveryTime) + TimeSpan.FromSeconds(GetEffectInfo(1).CalcValue() * _healedTargets); - GetCaster().GetSpellHistory().StartCooldown(GetSpellInfo(), 0, GetSpell(), false, cooldown); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); - AfterHit.Add(new(CountEffectivelyHealedTarget)); - AfterCast.Add(new(HandleCooldown)); - } + return RandomHelper.randChance(_procAttempts++ - 2); } - [Script] // 204288 - Earth Shield - class spell_sha_earth_shield : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + _procAttempts = 0; + + Unit target = eventInfo.GetActor(); + + int duration = GetEffect(0).GetAmount(); + Aura ascendanceAura = target.GetAura(_triggeredSpellId); + if (ascendanceAura != null) + duration += ascendanceAura.GetDuration(); + + target.CastSpell(target, _triggeredSpellId, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.EarthShieldHeal); + TriggerFlags = TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnoreCastInProgress, + TriggeringSpell = eventInfo.GetProcSpell(), + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.Duration, duration) } + }); + } + + public override void Register() + { + ChrSpecialization specialization = ChrSpecialization.None; + Aura aura = GetAura(); + if (aura != null) // aura doesn't exist at startup validation + { + Player owner = aura.GetOwner()?.ToPlayer(); + if (owner != null) + specialization = owner.GetPrimarySpecialization(); } - bool CheckProc(ProcEventInfo eventInfo) + if (specialization == ChrSpecialization.None || specialization == ChrSpecialization.ShamanElemental) { - if (eventInfo.GetDamageInfo() == null || !HasEffect(1) || eventInfo.GetDamageInfo().GetDamage() < GetTarget().CountPctFromMaxHealth(GetEffect(1).GetAmount())) - return false; - return true; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - GetTarget().CastSpell(GetTarget(), SpellIds.EarthShieldHeal, new CastSpellExtraArgs(aurEff) - .SetOriginalCaster(GetCasterGUID())); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); + DoCheckEffectProc.Add(new(CheckProc, 1, AuraType.Dummy)); OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + _triggeringSpellId = SpellIds.LavaBurst; + _triggeredSpellId = SpellIds.AscendanceElemental; + } + + if (specialization == ChrSpecialization.None || specialization == ChrSpecialization.ShamanEnhancement) + { + DoCheckEffectProc.Add(new(CheckProc, 2, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 2, AuraType.Dummy)); + _triggeringSpellId = SpellIds.Stormstrike; + _triggeredSpellId = SpellIds.AscendanceEnhancement; + } + + if (specialization == ChrSpecialization.None || specialization == ChrSpecialization.ShamanRestoration) + { + DoCheckEffectProc.Add(new(CheckProc, 3, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 3, AuraType.Dummy)); + _triggeringSpellId = SpellIds.Riptide; + _triggeredSpellId = SpellIds.AscendanceRestoration; + } + } +} + +[Script] // 466772 - Doom Winds +class spell_sha_doom_winds : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DoomWindsDamage); + } + + void PeriodicTick(AuraEffect aurEff) + { + GetTarget().CastSpell(GetTarget().GetPosition(), SpellIds.DoomWindsDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(PeriodicTick, 2, AuraType.PeriodicDummy)); + } +} + +[Script] // 335902 - Doom Winds +class spell_sha_doom_winds_legendary : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DoomWindsLegendaryCooldown); + } + + bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + if (GetTarget().HasAura(SpellIds.DoomWindsLegendaryCooldown)) + return false; + + SpellInfo spellInfo = procInfo.GetSpellInfo(); + if (spellInfo == null) + return false; + + return spellInfo.HasLabel(SpellIds.LabelShamanWindfuryTotem); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 207778 - Downpour +class spell_sha_downpour : SpellScript +{ + int _healedTargets; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + void FilterTargets(List targets) + { + SelectRandomInjuredTargets(targets, 6, true); + } + + void CountEffectivelyHealedTarget() + { + // Cooldown increased for each target effectively healed + if (GetHitHeal() != 0) + ++_healedTargets; + } + + void HandleCooldown() + { + TimeSpan cooldown = TimeSpan.FromSeconds(GetSpellInfo().RecoveryTime) + TimeSpan.FromSeconds(GetEffectInfo(1).CalcValue() * _healedTargets); + GetCaster().GetSpellHistory().StartCooldown(GetSpellInfo(), 0, GetSpell(), false, cooldown); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly)); + AfterHit.Add(new(CountEffectivelyHealedTarget)); + AfterCast.Add(new(HandleCooldown)); + } +} + +[Script] // 204288 - Earth Shield +class spell_sha_earth_shield : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EarthShieldHeal); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetDamageInfo() == null || !HasEffect(1) || eventInfo.GetDamageInfo().GetDamage() < GetTarget().CountPctFromMaxHealth(GetEffect(1).GetAmount())) + return false; + return true; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + GetTarget().CastSpell(GetTarget(), SpellIds.EarthShieldHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff, + OriginalCaster = GetCasterGUID() + }); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 8042 - Earth Shock +class spell_sha_earth_shock : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.T29_2PElementalDamageBuff, 0)); + } + + void AddScriptedDamageMods() + { + AuraEffect t29 = GetCaster().GetAuraEffect(SpellIds.T29_2PElementalDamageBuff, 0); + if (t29 != null) + { + SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), 100 + t29.GetAmount())); + t29.GetBase().Remove(); } } - [Script] // 8042 - Earth Shock - class spell_sha_earth_shock : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((SpellIds.T292PElementalDamageBuff, 0)); - } + OnHit.Add(new(AddScriptedDamageMods)); + } +} - void AddScriptedDamageMods() +[Script] // 170374 - Earthen Rage (Passive) +class spell_sha_earthen_rage_passive : AuraScript +{ + ObjectGuid _procTargetGuid; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EarthenRagePeriodic, SpellIds.EarthenRageDamage); + } + + static bool CheckProc(ProcEventInfo procInfo) + { + return procInfo.GetSpellInfo() != null && procInfo.GetSpellInfo().Id != SpellIds.EarthenRageDamage; + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + _procTargetGuid = eventInfo.GetProcTarget().GetGUID(); + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.EarthenRagePeriodic, new CastSpellExtraArgs() { - AuraEffect t29 = GetCaster().GetAuraEffect(SpellIds.T292PElementalDamageBuff, 0); - if (t29 != null) + TriggerFlags = TriggerCastFlags.FullMask + }); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } + + public ObjectGuid GetProcTarGetGUID() { return _procTargetGuid; } +} + +[Script] // 170377 - Earthen Rage (Proc Aura) +class spell_sha_earthen_rage_proc_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EarthenRagePassive, SpellIds.EarthenRageDamage); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + PreventDefaultAction(); + Aura aura = GetCaster().GetAura(SpellIds.EarthenRagePassive); + if (aura != null) + { + spell_sha_earthen_rage_passive script = aura.GetScript(); + if (script != null) { - SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), 100 + t29.GetAmount())); - t29.GetBase().Remove(); - } - } - - public override void Register() - { - OnHit.Add(new(AddScriptedDamageMods)); - } - } - - [Script] // 170374 - Earthen Rage (Passive) - class spell_sha_earthen_rage_passive : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EarthenRagePeriodic, SpellIds.EarthenRageDamage); - } - - bool CheckProc(ProcEventInfo procInfo) - { - return procInfo.GetSpellInfo() != null && procInfo.GetSpellInfo().Id != SpellIds.EarthenRageDamage; - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - _procTargetGuid = eventInfo.GetProcTarget().GetGUID(); - eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.EarthenRagePeriodic, true); - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - - ObjectGuid _procTargetGuid; - - public ObjectGuid GetProcTargetGuid() - { - return _procTargetGuid; - } - } - - [Script] // 170377 - Earthen Rage (Proc Aura) - class spell_sha_earthen_rage_proc_AuraScript : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EarthenRagePassive, SpellIds.EarthenRageDamage); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - PreventDefaultAction(); - Aura aura = GetCaster().GetAura(SpellIds.EarthenRagePassive); - if (aura != null) - { - spell_sha_earthen_rage_passive script = aura.GetScript(); - if (script != null) + Unit procTarget = Global.ObjAccessor.GetUnit(GetCaster(), script.GetProcTarGetGUID()); + if (procTarget != null) { - Unit procTarget = ObjAccessor.GetUnit(GetCaster(), script.GetProcTargetGuid()); - if (procTarget != null) - GetTarget().CastSpell(procTarget, SpellIds.EarthenRageDamage, true); + GetTarget().CastSpell(procTarget, SpellIds.EarthenRageDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask + }); } } } + } - public override void Register() + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +// 61882 - Earthquake +[Script] // 8382 - AreaTriggerId +class areatrigger_sha_earthquake(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + TimeSpan _refreshTimer = TimeSpan.Zero; + TimeSpan _period = TimeSpan.FromSeconds(1); + List _stunnedUnits = new(); + float _damageMultiplier = 1.0f; + + public override void OnCreate(Spell creatingSpell) + { + Unit caster = at.GetCaster(); + if (caster != null) { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + AuraEffect earthquake = caster.GetAuraEffect(SpellIds.Earthquake, 1); + if (earthquake != null) + _period = TimeSpan.FromSeconds(earthquake.GetPeriod()); + } + + if (creatingSpell != null) + { + if (creatingSpell.m_customArg is float damageMultiplier) + _damageMultiplier = damageMultiplier; } } - // 61882 - Earthquake - [Script] // 8382 - AreaTriggerId - class areatrigger_sha_earthquake : AreaTriggerAI + public override void OnUpdate(uint diff) { - TimeSpan _refreshTimer; - TimeSpan _period; - HashSet _stunnedUnits = new(); - float _damageMultiplier; - - public areatrigger_sha_earthquake(AreaTrigger areatrigger) : base(areatrigger) - { - _refreshTimer = TimeSpan.FromSeconds(0); - _period = TimeSpan.FromSeconds(1); - _damageMultiplier = 1.0f; - } - - public override void OnCreate(Spell creatingSpell) + _refreshTimer -= TimeSpan.FromSeconds(diff); + while (_refreshTimer <= TimeSpan.Zero) { Unit caster = at.GetCaster(); if (caster != null) - { - AuraEffect earthquake = caster.GetAuraEffect(SpellIds.Earthquake, 1); - if (earthquake != null) - _period = TimeSpan.FromMilliseconds(earthquake.GetPeriod()); - } - - if (creatingSpell != null) - { - float damageMultiplier = (float)creatingSpell.m_customArg; - if (damageMultiplier != 0) - _damageMultiplier = damageMultiplier; - } - } - - public override void OnUpdate(uint diff) - { - _refreshTimer -= TimeSpan.FromMilliseconds(diff); - while (_refreshTimer <= TimeSpan.FromSeconds(0)) - { - Unit caster = at.GetCaster(); - if (caster != null) - caster.CastSpell(at.GetPosition(), SpellIds.EarthquakeTick, new CastSpellExtraArgs(TriggerCastFlags.FullMask) - .SetOriginalCaster(at.GetGUID()) - .AddSpellMod(SpellValueMod.BasePoint0, (int)(caster.SpellBaseDamageBonusDone(SpellSchoolMask.Nature) * 0.213f * _damageMultiplier))); - - _refreshTimer += _period; - } - } - - // Each target can only be stunned once by each earthquake - keep track of who we already stunned - public bool AddStunnedTarget(ObjectGuid guid) - { - return _stunnedUnits.Add(guid); - } - } - - [Script] // 61882 - Earthquake - class spell_sha_earthquake : SpellScript - { - (uint, uint)[] DamageBuffs = - { - (SpellIds.EchoesOfGreatSunderingLegendary, 1), - (SpellIds.EchoesOfGreatSunderingTalent, 0), - (SpellIds.T292PElementalDamageBuff, 0) - }; - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect(DamageBuffs); - } - - void SnapshotDamageMultiplier(uint effIndex) - { - float damageMultiplier = 1.0f; - foreach (var (spellId, effect) in DamageBuffs) - { - AuraEffect buff = GetCaster().GetAuraEffect(spellId, effect); - if (buff != null) + caster.CastSpell(at.GetPosition(), SpellIds.EarthquakeTick, new CastSpellExtraArgs() { - MathFunctions.AddPct(ref damageMultiplier, buff.GetAmount()); - buff.GetBase().Remove(); - } - } + TriggerFlags = TriggerCastFlags.FullMask, + OriginalCaster = at.GetGUID(), + SpellValueOverrides = { new(SpellValueMod.BasePoint0, (int)(caster.SpellBaseDamageBonusDone(SpellSchoolMask.Nature) * 0.213f * _damageMultiplier)) } + }); - if (damageMultiplier != 1.0f) - GetSpell().m_customArg = damageMultiplier; - } - - public override void Register() - { - OnEffectLaunch.Add(new(SnapshotDamageMultiplier, 2, SpellEffectName.CreateAreaTrigger)); + _refreshTimer += _period; } } - [Script] // 77478 - Earthquake tick - class spell_sha_earthquake_tick : SpellScript + // Each target can only be stunned once by each earthquake - keep track of who we already stunned + public bool AddStunnedTarget(ObjectGuid guid) { - public override bool Validate(SpellInfo spellInfo) + if (_stunnedUnits.Contains(guid)) + return false; + + _stunnedUnits.Add(guid); + return true; + } +} + +[Script] // 61882 - Earthquake +class spell_sha_earthquake : SpellScript +{ + static (uint, uint)[] DamageBuffs = + { + (SpellIds.EchoesOfGreatSunderingLegendary, 1), + (SpellIds.EchoesOfGreatSunderingTalent, 0), + (SpellIds.T29_2PElementalDamageBuff, 0) + }; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect(DamageBuffs); + } + + void SnapshotDamageMultiplier(uint effIndex) + { + float damageMultiplier = 1.0f; + foreach (var (spellId, effect) in DamageBuffs) { - return ValidateSpellInfo(SpellIds.EarthquakeKnockingDown) + AuraEffect buff = GetCaster().GetAuraEffect(spellId, effect); + if (buff != null) + { + MathFunctions.AddPct(ref damageMultiplier, buff.GetAmount()); + buff.GetBase().Remove(); + } + } + + if (damageMultiplier != 1.0f) + GetSpell().m_customArg = damageMultiplier; + } + + public override void Register() + { + OnEffectLaunch.Add(new(SnapshotDamageMultiplier, 2, SpellEffectName.CreateAreaTrigger)); + } +} + +[Script] // 77478 - Earthquake tick +class spell_sha_earthquake_tick : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EarthquakeKnockingDown) && ValidateSpellEffect((spellInfo.Id, 1)); - } + } - void HandleOnHit() + void HandleOnHit() + { + Unit target = GetHitUnit(); + if (target != null) { - Unit target = GetHitUnit(); - if (target != null) + if (RandomHelper.randChance(GetEffectInfo(1).CalcValue())) { - if (RandomHelper.randChance(GetEffectInfo(1).CalcValue())) + List areaTriggers = GetCaster().GetAreaTriggers(SpellIds.Earthquake); + var itr = areaTriggers.Find(at => at.GetGUID() == GetSpell().GetOriginalCasterGUID()); + if (itr != null) { - List areaTriggers = GetCaster().GetAreaTriggers(SpellIds.Earthquake); - var areaTrigger = areaTriggers.Find(at => at.GetGUID() == GetSpell().GetOriginalCasterGUID()); - if (areaTrigger != null) - { - areatrigger_sha_earthquake eq = areaTrigger.GetAI(); - if (eq != null) - if (eq.AddStunnedTarget(target.GetGUID())) - GetCaster().CastSpell(target, SpellIds.EarthquakeKnockingDown, true); - } + areatrigger_sha_earthquake eq = itr.GetAI(); + if (eq != null) + if (eq.AddStunnedTarget(target.GetGUID())) + GetCaster().CastSpell(target, SpellIds.EarthquakeKnockingDown, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); } } } + } - public override void Register() + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +// 117014 - Elemental Blast +[Script] // 120588 - Elemental Blast Overload +class spell_sha_elemental_blast : SpellScript +{ + static uint[] BuffSpells = [SpellIds.ElementalBlastCrit, SpellIds.ElementalBlastHaste, SpellIds.ElementalBlastMastery]; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ElementalBlastCrit, SpellIds.ElementalBlastHaste, SpellIds.ElementalBlastMastery) + && ValidateSpellEffect((SpellIds.T29_2PElementalDamageBuff, 0)); + } + + void TriggerBuff() + { + Unit caster = GetCaster(); + double total = 0.0; + for (var i = 0; i < BuffSpells.Length; ++i) + total += !caster.HasAura(BuffSpells[i]) ? 1.0f : 0.0f; + + uint spellId() { - OnHit.Add(new(HandleOnHit)); + if (total > 0.0) + return BuffSpells.SelectRandomElementByWeight(buffSpell => !caster.HasAura(buffSpell) ? 1.0f : 0.0f); + + // refresh random one if we have them all + return BuffSpells.SelectRandom(); + } + + GetCaster().CastSpell(GetCaster(), spellId(), new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + } + + void AddScriptedDamageMods() + { + AuraEffect t29 = GetCaster().GetAuraEffect(SpellIds.T29_2PElementalDamageBuff, 0); + if (t29 != null) + { + SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), 100 + t29.GetAmount())); + t29.GetBase().Remove(); } } - // 117014 - Elemental Blast - [Script] // 120588 - Elemental Blast Overload - class spell_sha_elemental_blast : SpellScript + public override void Register() { - uint[] BuffSpells = { SpellIds.ElementalBlastCrit, SpellIds.ElementalBlastHaste, SpellIds.ElementalBlastMastery }; + AfterCast.Add(new(TriggerBuff)); + OnHit.Add(new(AddScriptedDamageMods)); + } +} - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ElementalBlastCrit, SpellIds.ElementalBlastHaste, SpellIds.ElementalBlastMastery, SpellIds.ElementalBlastEnergize, SpellIds.MaelstromController) - && ValidateSpellEffect((SpellIds.MaelstromController, 10), (SpellIds.T292PElementalDamageBuff, 0)); - } - - void HandleEnergize(uint effIndex) - { - AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, GetSpellInfo().Id == SpellIds.ElementalBlast ? 9 : 10u); - if (energizeAmount != null) - GetCaster().CastSpell(GetCaster(), SpellIds.ElementalBlastEnergize, new CastSpellExtraArgs(energizeAmount) - .AddSpellMod(SpellValueMod.BasePoint0, energizeAmount.GetAmount())); - } - - void TriggerBuff() - { - Unit caster = GetCaster(); - uint spellId = BuffSpells.SelectRandomElementByWeight(buffSpellId => !caster.HasAura(buffSpellId) ? 1.0f : 0.0f); - - GetCaster().CastSpell(GetCaster(), spellId, TriggerCastFlags.FullMask); - } - - void AddScriptedDamageMods() - { - AuraEffect t29 = GetCaster().GetAuraEffect(SpellIds.T292PElementalDamageBuff, 0); - if (t29 != null) - { - SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), 100 + t29.GetAmount())); - t29.GetBase().Remove(); - } - } - - public override void Register() - { - OnEffectLaunch.Add(new(HandleEnergize, 0, SpellEffectName.SchoolDamage)); - AfterCast.Add(new(TriggerBuff)); - OnHit.Add(new(AddScriptedDamageMods)); - } +[Script] // 384355 - Elemental Weapons +class spell_sha_elemental_weapons : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ElementalWeaponsBuff); } - [Script] // 318038 - Flametongue Weapon - class spell_sha_flametongue_weapon : SpellScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FlametongueWeaponEnchant); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleEffectHitTarget(uint effIndex) - { - Player player = GetCaster().ToPlayer(); - byte slot = EquipmentSlot.MainHand; - if (player.GetPrimarySpecialization() == ChrSpecialization.ShamanEnhancement) - slot = EquipmentSlot.OffHand; - - Item targetItem = player.GetItemByPos(InventorySlots.Bag0, slot); - if (targetItem == null || !targetItem.GetTemplate().IsWeapon()) - return; - - player.CastSpell(targetItem, SpellIds.FlametongueWeaponEnchant, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); - } + return GetUnitOwner().IsPlayer(); } - [Script] // 319778 - Flametongue - SpellIds.FlametongueWeaponAura - class spell_sha_flametongue_weapon_AuraScript : AuraScript + void CheckEnchantments() { - public override bool Validate(SpellInfo spellInfo) + Player owner = GetUnitOwner().ToPlayer(); + int enchatmentCount = 0; + if (owner.HasAura(SpellIds.FlametongueWeaponAura)) + ++enchatmentCount; + if (owner.HasAura(SpellIds.WindfuryAura)) + ++enchatmentCount; + + int valuePerStack = GetEffect(0).GetAmount(); + Aura buff = owner.GetAura(SpellIds.ElementalWeaponsBuff); + if (buff != null) { - return ValidateSpellInfo(SpellIds.FlametongueAttack); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - Unit attacker = eventInfo.GetActor(); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, Math.Max(1, (int)(attacker.GetTotalAttackPowerValue(WeaponAttackType.BaseAttack) * 0.0264f))); - attacker.CastSpell(eventInfo.GetActionTarget(), SpellIds.FlametongueAttack, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - [Script] // 73920 - Healing Rain (Aura) - class spell_sha_healing_rain_AuraScript : AuraScript - { - ObjectGuid _visualDummy; - Position _dest; - - public void SetVisualDummy(TempSummon summon) - { - _visualDummy = summon.GetGUID(); - _dest = summon.GetPosition(); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - GetTarget().CastSpell(_dest, SpellIds.HealingRainHeal, aurEff); - } - - void HandleEffecRemoved(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Creature summon = ObjectAccessor.GetCreature(GetTarget(), _visualDummy); - if (summon != null) - summon.DespawnOrUnsummon(); - } - - public override void Register() - { - OnEffectRemove.Add(new(HandleEffecRemoved, 1, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 1, AuraType.PeriodicDummy)); - } - } - - [Script] // 73920 - Healing Rain - class spell_sha_healing_rain : SpellScript - { - const uint NpcHealingRainInvisibleStalker = 73400; - - void InitializeVisualStalker() - { - Aura aura = GetHitAura(); - if (aura != null) - { - WorldLocation dest = GetExplTargetDest(); - if (dest != null) - { - var duration = TimeSpan.FromMilliseconds(GetSpellInfo().CalcDuration(GetOriginalCaster())); - TempSummon summon = GetCaster().GetMap().SummonCreature(NpcHealingRainInvisibleStalker, dest, null, duration, GetOriginalCaster()); - if (summon == null) - return; - - summon.CastSpell(summon, SpellIds.HealingRainVisual, true); - - spell_sha_healing_rain_AuraScript script = aura.GetScript(); - if (script != null) - script.SetVisualDummy(summon); - } - } - } - - public override void Register() - { - AfterHit.Add(new(InitializeVisualStalker)); - } - } - - [Script] // 73921 - Healing Rain - class spell_sha_healing_rain_target_limit : SpellScript - { - void SelectTargets(List targets) - { - SelectRandomInjuredTargets(targets, 6, true); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(SelectTargets, 0, Targets.UnitDestAreaAlly)); - } - } - - [Script] // 52042 - Healing Stream Totem - class spell_sha_healing_stream_totem_heal : SpellScript - { - void SelectTargets(List targets) - { - SelectRandomInjuredTargets(targets, 1, true); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(SelectTargets, 0, Targets.UnitDestAreaAlly)); - } - } - - [Script] // 210714 - Icefury - class spell_sha_icefury : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FrostShockEnergize); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, SpellIds.FrostShockEnergize, TriggerCastFlags.IgnoreCastInProgress); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 1, AuraType.AddPctModifier)); - } - } - - [Script] // 23551 - Lightning Shield T2 Bonus - class spell_sha_item_lightning_shield : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ItemLightningShield); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.ItemLightningShield, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 23552 - Lightning Shield T2 Bonus - class spell_sha_item_lightning_shield_trigger : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ItemLightningShieldDamage); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellIds.ItemLightningShieldDamage, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 23572 - Mana Surge - class spell_sha_item_mana_surge : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ItemManaSurge); - } - - bool CheckProc(ProcEventInfo eventInfo) - { - return eventInfo.GetProcSpell() != null; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - int? manaCost = eventInfo.GetProcSpell().GetPowerTypeCostAmount(PowerType.Mana); - if (manaCost.HasValue) - { - int mana = MathFunctions.CalculatePct(manaCost.Value, 35); - if (mana > 0) - { - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, mana); - GetTarget().CastSpell(GetTarget(), SpellIds.ItemManaSurge, args); - } - } - } - - public override void Register() - { - DoCheckProc.Add(new(CheckProc)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 40463 - Shaman Tier 6 Trinket - class spell_sha_item_t6_trinket : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.EnergySurge, SpellIds.PowerSurge); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null) - return; - - uint spellId; - int chance; - - // Lesser Healing Wave - if (spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x00000080u)) - { - spellId = SpellIds.EnergySurge; - chance = 10; - } - // Lightning Bolt - else if (spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x00000001u)) - { - spellId = SpellIds.EnergySurge; - chance = 15; - } - // Stormstrike - else if (spellInfo.SpellFamilyFlags[1].HasAnyFlag(0x00000010u)) - { - spellId = SpellIds.PowerSurge; - chance = 50; - } + if (enchatmentCount != 0) + foreach (AuraEffect aurEff in buff.GetAuraEffects()) + aurEff.ChangeAmount(valuePerStack * enchatmentCount / 10); else - return; - - if (RandomHelper.randChance(chance)) - eventInfo.GetActor().CastSpell(null, spellId, true); + buff.Remove(); } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 70811 - Item - Shaman T10 Elemental 2P Bonus - class spell_sha_item_t10_elemental_2p_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ElementalMastery); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Player target = GetTarget().ToPlayer(); - if (target != null) - target.GetSpellHistory().ModifyCooldown(SpellIds.ElementalMastery, TimeSpan.FromMilliseconds(-aurEff.GetAmount())); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } - } - - [Script] // 189063 - Lightning Vortex (proc 185881 Item - Shaman T18 Elemental 4P Bonus) - class spell_sha_item_t18_elemental_4p_bonus : AuraScript - { - void DiminishHaste(AuraEffect aurEff) - { - PreventDefaultAction(); - AuraEffect hasteBuff = GetEffect(0); - if (hasteBuff != null) - hasteBuff.ChangeAmount(hasteBuff.GetAmount() - aurEff.GetAmount()); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(DiminishHaste, 1, AuraType.PeriodicDummy)); - } - } - - [Script] // 51505 - Lava burst - class spell_sha_lava_burst : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.PathOfFlamesTalent, SpellIds.PathOfFlamesSpread, SpellIds.LavaSurge); - } - - void HandleScript(uint effIndex) - { - Unit caster = GetCaster(); - if (caster != null) - if (caster.HasAura(SpellIds.PathOfFlamesTalent)) - caster.CastSpell(GetHitUnit(), SpellIds.PathOfFlamesSpread, GetSpell()); - } - - void EnsureLavaSurgeCanBeImmediatelyConsumed() - { - Unit caster = GetCaster(); - - Aura lavaSurge = caster.GetAura(SpellIds.LavaSurge); - if (lavaSurge != null) + else if (enchatmentCount != 0) + owner.CastSpell(owner, SpellIds.ElementalWeaponsBuff, new CastSpellExtraArgs() { - if (!GetSpell().m_appliedMods.Contains(lavaSurge)) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { - uint chargeCategoryId = GetSpellInfo().ChargeCategoryId; - - // Ensure we have at least 1 usable charge after cast to allow next cast immediately - if (!caster.GetSpellHistory().HasCharge(chargeCategoryId)) - caster.GetSpellHistory().RestoreCharge(chargeCategoryId); + new( SpellValueMod.BasePoint0, valuePerStack * enchatmentCount / 10 ), + new( SpellValueMod.BasePoint1, valuePerStack * enchatmentCount / 10 ) } + }); + } + + void RemoveAllBuffs(AuraEffect aurEff, AuraEffectHandleModes mode) + { + GetUnitOwner().RemoveAurasDueToSpell(SpellIds.ElementalWeaponsBuff); + } + + public override void Register() + { + OnHeartbeat.Add(new(CheckEnchantments)); + AfterEffectRemove.Add(new(RemoveAllBuffs, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +class FireNovaTargetCheck : ICheck +{ + public float MaxSearchRange = 40.0f; + public Unit Shaman; + + public bool Invoke(Unit candidate) + { + return candidate.IsWithinDist3d(Shaman, MaxSearchRange) && candidate.HasAura(SpellIds.FlameShock, Shaman.GetGUID()); + } +} + +[Script] // 333974 - Fire Nova +class spell_sha_fire_nova : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FireNovaDamage); + } + + void TriggerDamage(uint effIndex) + { + Unit shaman = GetCaster(); + List targets = new(); + FireNovaTargetCheck check = new() { Shaman = shaman }; + UnitListSearcher searcher = new(shaman, targets, check); + Cell.VisitAllObjects(shaman, searcher, check.MaxSearchRange); + + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + args.SetTriggeringSpell(GetSpell()); + + foreach (Unit target in targets) + shaman.CastSpell(target, SpellIds.FireNovaDamage, args); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(TriggerDamage, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 466620 - Flame Shock +class spell_sha_flame_shock_fire_nova_enabler : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlameShock, SpellIds.FireNovaEnabler); + } + + void CheckFlameShocks(AuraEffect aurEff) + { + Unit shaman = GetTarget(); + FireNovaTargetCheck check = new() { Shaman = shaman }; + UnitSearcher searcher = new(shaman, check); + Cell.VisitAllObjects(shaman, searcher, check.MaxSearchRange); + if (searcher.GetResult() != null) + shaman.CastSpell(shaman, SpellIds.FireNovaEnabler, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + else + shaman.RemoveAurasDueToSpell(SpellIds.FireNovaEnabler); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(CheckFlameShocks, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 318038 - Flametongue Weapon +class spell_sha_flametongue_weapon : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlametongueWeaponEnchant); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleEffectHitTarget(uint effIndex) + { + Player player = GetCaster().ToPlayer(); + byte slot = EquipmentSlot.MainHand; + if (player.GetPrimarySpecialization() == ChrSpecialization.ShamanEnhancement) + slot = EquipmentSlot.OffHand; + + Item targetItem = player.GetItemByPos(InventorySlots.Bag0, slot); + if (targetItem == null || !targetItem.GetTemplate().IsWeapon()) + return; + + player.CastSpell(targetItem, SpellIds.FlametongueWeaponEnchant, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 319778 - Flametongue - SpellIds.FlametongueWeaponAura +class spell_sha_flametongue_weapon_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlametongueAttack); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + eventInfo.GetActor().CastSpell(eventInfo.GetActionTarget(), SpellIds.FlametongueAttack, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 334196 - Hailstorm +class spell_sha_hailstorm : AuraScript +{ + void CalcCleaveMod(AuraEffect aurEff, ref SpellModifier spellMod) + { + if (spellMod == null) + { + SpellModifierByClassMask mod = new SpellModifierByClassMask(GetAura()); + mod.op = SpellModOp.ChainTargets; + mod.type = SpellModType.Flat; + mod.spellId = GetId(); + mod.mask = new FlagArray128(0x80000000, 0x00000000, 0x00000000, 0x00000000); + + spellMod = mod; + } + + AuraEffect hailstormPassive = GetUnitOwner().GetAuraEffect(SpellIds.HailstormTalent, 0); + if (hailstormPassive != null) + { + int targetCap = hailstormPassive.GetAmount() / aurEff.GetBaseAmount(); + ((SpellModifierByClassMask)spellMod).value = Math.Min(targetCap, GetStackAmount()) + 1; + } + } + + public override void Register() + { + DoEffectCalcSpellMod.Add(new(CalcCleaveMod, 1, AuraType.Dummy)); + } +} + +[Script] // 73920 - Healing Rain (Aura) +class spell_sha_healing_rain_aura : AuraScript +{ + ObjectGuid _visualDummy; + Position _dest; + + public void SetVisualDummy(TempSummon summon) + { + _visualDummy = summon.GetGUID(); + _dest = summon.GetPosition(); + } + + public Position GetPosition() { return _dest; } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + GetTarget().CastSpell(_dest, SpellIds.HealingRainHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff + }); + } + + void HandleEffecRemoved(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Creature summon = ObjectAccessor.GetCreature(GetTarget(), _visualDummy); + if (summon != null) + summon.DespawnOrUnsummon(); + } + + public override void Register() + { + OnEffectRemove.Add(new(HandleEffecRemoved, 1, AuraType.PeriodicDummy, AuraEffectHandleModes.Real)); + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 1, AuraType.PeriodicDummy)); + } +} + +[Script] // 73920 - Healing Rain +class spell_sha_healing_rain : SpellScript +{ + const uint NpcHealingRainInvisibleStalker = 73400; + + void InitializeVisualStalker() + { + Aura aura = GetHitAura(); + if (aura != null) + { + WorldLocation dest = GetExplTargetDest(); + if (dest != null) + { + TimeSpan duration = TimeSpan.FromSeconds(GetSpellInfo().CalcDuration(GetOriginalCaster())); + TempSummon summon = GetCaster().GetMap().SummonCreature(NpcHealingRainInvisibleStalker, dest, null, duration, GetOriginalCaster()); + if (summon == null) + return; + + summon.CastSpell(summon, SpellIds.HealingRainVisual, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + + spell_sha_healing_rain_aura script = aura.GetScript(); + if (script != null) + script.SetVisualDummy(summon); } } + } - public override void Register() + public override void Register() + { + AfterHit.Add(new(InitializeVisualStalker)); + } +} + +[Script] // 73921 - Healing Rain +class spell_sha_healing_rain_target_limit : SpellScript +{ + void SelectTargets(List targets) + { + SelectRandomInjuredTargets(targets, 6, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(SelectTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +[Script] // 52042 - Healing Stream Totem +class spell_sha_healing_stream_totem_heal : SpellScript +{ + void SelectTargets(List targets) + { + SelectRandomInjuredTargets(targets, 1, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(SelectTargets, 0, Targets.UnitDestAreaAlly)); + } +} + +[Script] // 201900 - Hot Hand +class spell_sha_hot_hand : AuraScript +{ + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActor().HasAura(SpellIds.FlametongueWeaponAura); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + } +} + +[Script] // 342240 - Ice Strike +class spell_sha_ice_strike : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return spell_sha_maelstrom_weapon_base.Validate(); + } + + void EnergizeMaelstrom(uint effIndex) + { + spell_sha_maelstrom_weapon_base.GenerateMaelstromWeapon(GetCaster(), GetEffectValue()); + } + + public override void Register() + { + OnEffectHit.Add(new(EnergizeMaelstrom, 3, SpellEffectName.Dummy)); + } +} + +[Script] // 466467 - Ice Strike +class spell_sha_ice_strike_proc : AuraScript +{ + int _attemptCount; + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IceStrikeOverrideAura); + } + + public override void Register() { } + + public void AttemptProc() + { + if (!RandomHelper.randChance(++_attemptCount * 7)) + return; + + _attemptCount = 0; + Unit shaman = GetUnitOwner(); + shaman.CastSpell(shaman, SpellIds.IceStrikeOverrideAura, new CastSpellExtraArgs() { - OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TriggerMissile)); - AfterCast.Add(new(EnsureLavaSurgeCanBeImmediatelyConsumed)); + TriggerFlags = TriggerCastFlags.DontReportCastError + }); + } +} + +[Script] // 210714 - Icefury +class spell_sha_icefury : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FrostShockEnergize); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.FrostShockEnergize, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.IgnoreCastInProgress }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 1, AuraType.AddPctModifier)); + } +} + +[Script] // 23551 - Lightning Shield T2 Bonus +class spell_sha_item_lightning_shield : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ItemLightningShield); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(eventInfo.GetProcTarget(), SpellIds.ItemLightningShield, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 23552 - Lightning Shield T2 Bonus +class spell_sha_item_lightning_shield_trigger : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ItemLightningShieldDamage); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.ItemLightningShieldDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 23572 - Mana Surge +class spell_sha_item_mana_surge : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ItemManaSurge); + } + + static bool CheckProc(ProcEventInfo eventInfo) + { + return eventInfo.GetProcSpell() != null; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + var manaCost = eventInfo.GetProcSpell().GetPowerTypeCostAmount(PowerType.Mana); + if (manaCost.HasValue) + { + int mana = MathFunctions.CalculatePct(manaCost.Value, 35); + if (mana > 0) + { + GetTarget().CastSpell(GetTarget(), SpellIds.ItemManaSurge, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, mana) } + }); + } } } - // 285452 - Lava Burst damage - [Script] // 285466 - Lava Burst Overload damage - class spell_sha_lava_crit_chance : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + DoCheckProc.Add(new(CheckProc)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell)); + } +} + +[Script] // 40463 - Shaman Tier 6 Trinket +class spell_sha_item_t6_trinket : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.EnergySurge, SpellIds.PowerSurge); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null) + return; + + uint spellId; + int chance; + + // Lesser Healing Wave + if ((spellInfo.SpellFamilyFlags[0] & 0x00000080) != 0) { - return ValidateSpellInfo(SpellIds.FlameShock); + spellId = SpellIds.EnergySurge; + chance = 10; } - - void CalcCritChance(Unit victim, ref float chance) + // Lightning Bolt + else if ((spellInfo.SpellFamilyFlags[0] & 0x00000001) != 0) { - Unit caster = GetCaster(); - - if (caster == null || victim == null) - return; - - if (victim.HasAura(SpellIds.FlameShock, caster.GetGUID())) - if (victim.GetTotalAuraModifier(AuraType.ModAttackerSpellAndWeaponCritChance) > -100) - chance = 100.0f; + spellId = SpellIds.EnergySurge; + chance = 15; } - - public override void Register() + // Stormstrike + else if ((spellInfo.SpellFamilyFlags[1] & 0x00000010) != 0) { - OnCalcCritChance.Add(new(CalcCritChance)); + spellId = SpellIds.PowerSurge; + chance = 50; + } + else + return; + + if (RandomHelper.randChance(chance)) + eventInfo.GetActor().CastSpell(null, spellId, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 70811 - Item - Shaman T10 Elemental 2P Bonus +class spell_sha_item_t10_elemental_2p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ElementalMastery); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Player target = GetTarget().ToPlayer(); + if (target != null) + target.GetSpellHistory().ModifyCooldown(SpellIds.ElementalMastery, TimeSpan.FromSeconds(-aurEff.GetAmount())); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 189063 - Lightning Vortex (proc 185881 Item - Shaman T18 Elemental 4P Bonus) +class spell_sha_item_t18_elemental_4p_bonus : AuraScript +{ + void DiminishHaste(AuraEffect aurEff) + { + PreventDefaultAction(); + AuraEffect hasteBuff = GetEffect(0); + if (hasteBuff != null) + hasteBuff.ChangeAmount(hasteBuff.GetAmount() - aurEff.GetAmount()); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(DiminishHaste, 1, AuraType.PeriodicDummy)); + } +} + +[Script] // 51505 - Lava burst +class spell_sha_lava_burst : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PathOfFlamesTalent, SpellIds.PathOfFlamesSpread, SpellIds.LavaSurge); + } + + void HandleScript(uint effIndex) + { + Unit caster = GetCaster(); + if (caster != null) + if (caster.HasAura(SpellIds.PathOfFlamesTalent)) + caster.CastSpell(GetHitUnit(), SpellIds.PathOfFlamesSpread, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringSpell = GetSpell() + }); + } + + void EnsureLavaSurgeCanBeImmediatelyConsumed() + { + Unit caster = GetCaster(); + + Aura lavaSurge = caster.GetAura(SpellIds.LavaSurge); + if (lavaSurge != null) + { + if (!GetSpell().m_appliedMods.Contains(lavaSurge)) + { + uint chargeCategoryId = GetSpellInfo().ChargeCategoryId; + + // Ensure we have at least 1 usable charge after cast to allow next cast immediately + if (!caster.GetSpellHistory().HasCharge(chargeCategoryId)) + caster.GetSpellHistory().RestoreCharge(chargeCategoryId); + } } } - [Script] // 77756 - Lava Surge - class spell_sha_lava_surge : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LavaSurge, SpellIds.IgneousPotential); - } + OnEffectHitTarget.Add(new(HandleScript, 0, SpellEffectName.TriggerMissile)); + AfterCast.Add(new(EnsureLavaSurgeCanBeImmediatelyConsumed)); + } +} - bool CheckProcChance(AuraEffect aurEff, ProcEventInfo eventInfo) - { - int procChance = aurEff.GetAmount(); - AuraEffect igneousPotential = GetTarget().GetAuraEffect(SpellIds.IgneousPotential, 0); - if (igneousPotential != null) - procChance += igneousPotential.GetAmount(); - - return RandomHelper.randChance(procChance); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - GetTarget().CastSpell(GetTarget(), SpellIds.LavaSurge, true); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProcChance, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } +// 285452 - Lava Burst damage +[Script] // 285466 - Lava Burst Overload damage +class spell_sha_lava_crit_chance : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlameShock); } - [Script] // 77762 - Lava Surge - class spell_sha_lava_surge_proc : SpellScript + void CalcCritChance(Unit victim, ref float chance) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LavaBurst); - } + Unit caster = GetCaster(); - public override bool Load() - { - return GetCaster().IsPlayer(); - } + if (caster == null || victim == null) + return; - void ResetCooldown() - { - GetCaster().GetSpellHistory().RestoreCharge(SpellMgr.GetSpellInfo(SpellIds.LavaBurst, GetCastDifficulty()).ChargeCategoryId); - } - - public override void Register() - { - AfterHit.Add(new(ResetCooldown)); - } + if (victim.HasAura(SpellIds.FlameShock, caster.GetGUID())) + if (victim.GetTotalAuraModifier(AuraType.ModAttackerSpellAndWeaponCritChance) > -100) + chance = 100.0f; } - [Script] // 188196 - Lightning Bolt - class spell_sha_lightning_bolt : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LightningBoltEnergize, SpellIds.MaelstromController) + OnCalcCritChance.Add(new(CalcCritChance)); + } +} + +[Script] // 60103 - Lava Lash +class spell_sha_lava_lash : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)) + && ValidateSpellInfo(SpellIds.FlametongueWeaponAura); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void AddBonusFlametongueDamage(SpellEffectInfo effectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + Player caster = GetCaster().ToPlayer(); + ObjectGuid offhandItemGuid = caster.GetWeaponForAttack(GetSpellInfo().GetAttackType()).GetGUID(); + if (GetCaster().HasAura(SpellIds.FlametongueWeaponAura, ObjectGuid.Empty, offhandItemGuid)) + MathFunctions.AddPct(ref pctMod, GetSpell().CalculateDamage(GetEffectInfo(1), victim)); + } + + public override void Register() + { + CalcDamage.Add(new(AddBonusFlametongueDamage)); + } +} + +[Script] // 77756 - Lava Surge +class spell_sha_lava_surge : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LavaSurge, SpellIds.IgneousPotential); + } + + bool CheckProcChance(AuraEffect aurEff, ProcEventInfo eventInfo) + { + int procChance = aurEff.GetAmount(); + AuraEffect igneousPotential = GetTarget().GetAuraEffect(SpellIds.IgneousPotential, 0); + if (igneousPotential != null) + procChance += igneousPotential.GetAmount(); + + return RandomHelper.randChance(procChance); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), SpellIds.LavaSurge, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProcChance, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 77762 - Lava Surge +class spell_sha_lava_surge_proc : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LavaBurst); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void ResetCooldown() + { + GetCaster().GetSpellHistory().RestoreCharge(Global.SpellMgr.GetSpellInfo(SpellIds.LavaBurst, GetCastDifficulty()).ChargeCategoryId); + } + + public override void Register() + { + AfterHit.Add(new(ResetCooldown)); + } +} + +[Script] // 188196 - Lightning Bolt +class spell_sha_lightning_bolt : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LightningBoltEnergize) && ValidateSpellEffect((SpellIds.MaelstromController, 0)); - } - - void HandleScript(uint effIndex) - { - AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 0); - if (energizeAmount != null) - GetCaster().CastSpell(GetCaster(), SpellIds.LightningBoltEnergize, new CastSpellExtraArgs(energizeAmount) - .AddSpellMod(SpellValueMod.BasePoint0, energizeAmount.GetAmount())); - } - - public override void Register() - { - OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); - } } - [Script] // 45284 - Lightning Bolt Overload - class spell_sha_lightning_bolt_overload : SpellScript + void HandleScript(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LightningBoltOverloadEnergize, SpellIds.MaelstromController) + AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 0); + if (energizeAmount != null) + GetCaster().CastSpell(GetCaster(), SpellIds.LightningBoltEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = energizeAmount, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, energizeAmount.GetAmount()) } + }); + } + + public override void Register() + { + OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 45284 - Lightning Bolt Overload +class spell_sha_lightning_bolt_overload : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LightningBoltOverloadEnergize) && ValidateSpellEffect((SpellIds.MaelstromController, 1)); - } - - void HandleScript(uint effIndex) - { - AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 1); - if (energizeAmount != null) - GetCaster().CastSpell(GetCaster(), SpellIds.LightningBoltOverloadEnergize, new CastSpellExtraArgs(energizeAmount) - .AddSpellMod(SpellValueMod.BasePoint0, energizeAmount.GetAmount())); - } - - public override void Register() - { - OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); - } } - [Script] // 192223 - Liquid Magma Totem (erupting hit spell) - class spell_sha_liquid_magma_totem : SpellScript + void HandleScript(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.LiquidMagmaHit); - } - - void HandleEffectHitTarget(uint effIndex) - { - Unit hitUnit = GetHitUnit(); - if (hitUnit != null) - GetCaster().CastSpell(hitUnit, SpellIds.LiquidMagmaHit, true); - } - - void HandleTargetSelect(List targets) - { - // choose one random target from targets - if (targets.Count > 1) + AuraEffect energizeAmount = GetCaster().GetAuraEffect(SpellIds.MaelstromController, 1); + if (energizeAmount != null) + GetCaster().CastSpell(GetCaster(), SpellIds.LightningBoltOverloadEnergize, new CastSpellExtraArgs() { - WorldObject selected = targets.SelectRandom(); - targets.Clear(); - targets.Add(selected); - } - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = energizeAmount, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, energizeAmount.GetAmount()) } + }); + } - public override void Register() + public override void Register() + { + OnEffectLaunch.Add(new(HandleScript, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 192223 - Liquid Magma Totem (erupting hit spell) +class spell_sha_liquid_magma_totem : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LiquidMagmaHit); + } + + void HandleEffectHitTarget(uint effIndex) + { + Unit hitUnit = GetHitUnit(); + if (hitUnit != null) + GetCaster().CastSpell(hitUnit, SpellIds.LiquidMagmaHit, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + } + + void HandleTargetSelect(List targets) + { + // choose one random target from targets + if (targets.Count > 1) { - OnObjectAreaTargetSelect.Add(new(HandleTargetSelect, 0, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); + WorldObject selected = targets.SelectRandom(); + targets.Clear(); + targets.Add(selected); } } - [Script] // 168534 - Mastery: Elemental Overload (passive) - class spell_sha_mastery_elemental_overload : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnObjectAreaTargetSelect.Add(new(HandleTargetSelect, 0, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 187880 - Maelstrom Weapon +class spell_sha_maelstrom_weapon : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return spell_sha_maelstrom_weapon_base.Validate(); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procEvent) + { + spell_sha_maelstrom_weapon_base.GenerateMaelstromWeapon(GetTarget(), 1); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 344179 - Maelstrom Weapon +class spell_sha_maelstrom_weapon_proc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return spell_sha_maelstrom_weapon_base.Validate(); + } + + bool CheckProc(ProcEventInfo procEvent) + { + Spell procSpell = procEvent.GetProcSpell(); + if (procSpell == null) + return false; + + Aura maelstromSpellMod = GetTarget().GetAura(SpellIds.MaelstromWeaponModAura); + if (maelstromSpellMod == null) + return false; + + return procSpell.m_appliedMods.Contains(maelstromSpellMod); + } + + void RemoveMaelstromAuras(ProcEventInfo procEvent) + { + Unit shaman = GetTarget(); + int stacksToConsume = 5; + if (shaman.HasAura(SpellIds.OverflowingMaelstromTalent)) + stacksToConsume = 10; + + spell_sha_maelstrom_weapon_base.ConsumeMaelstromWeapon(shaman, GetAura(), stacksToConsume, procEvent.GetProcSpell()); + } + + void ExpireMaelstromAuras(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit shaman = GetTarget(); + AuraRemoveMode removeMode = GetTargetApplication().GetRemoveMode(); + shaman.RemoveAurasDueToSpell(SpellIds.OverflowingMaelstromAura, ObjectGuid.Empty, 0, removeMode); + shaman.RemoveAurasDueToSpell(SpellIds.MaelstromWeaponModAura, ObjectGuid.Empty, 0, removeMode); + shaman.RemoveAurasDueToSpell(SpellIds.MaelstromWeaponOverlay, ObjectGuid.Empty, 0, removeMode); + shaman.RemoveAurasDueToSpell(SpellIds.MaelstromWeaponOverlayHeals, ObjectGuid.Empty, 0, removeMode); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnProc.Add(new(RemoveMaelstromAuras)); + AfterEffectRemove.Add(new(ExpireMaelstromAuras, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} + +[Script] // 168534 - Mastery: Elemental Overload (passive) +class spell_sha_mastery_elemental_overload : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo + ( + SpellIds.LightningBolt, + SpellIds.LightningBoltOverload, + SpellIds.ElementalBlast, + SpellIds.ElementalBlastOverload, + SpellIds.Icefury, + SpellIds.IcefuryOverload, + SpellIds.LavaBurst, + SpellIds.LavaBurstOverload, + SpellIds.ChainLightning, + SpellIds.ChainLightningOverload, + SpellIds.Stormkeeper + ); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null || eventInfo.GetProcSpell() == null) + return false; + + if (GetTriggeredSpellId(spellInfo.Id) == null) + return false; + + float chance = aurEff.GetAmount(); // Mastery % amount + + if (spellInfo.Id == SpellIds.ChainLightning) + chance /= 3.0f; + + Aura stormkeeper = eventInfo.GetActor().GetAura(SpellIds.Stormkeeper); + if (stormkeeper != null && eventInfo.GetProcSpell().m_appliedMods.Contains(stormkeeper)) + chance = 100.0f; + + return RandomHelper.randChance(chance); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + PreventDefaultAction(); + + Unit caster = procInfo.GetActor(); + + var targets = new CastSpellTargetArg(procInfo.GetProcTarget()); + var overloadSpellId = GetTriggeredSpellId(procInfo.GetSpellInfo().Id); + var originalCastId = procInfo.GetProcSpell().m_castId; + caster.m_Events.AddEventAtOffset(() => { - return ValidateSpellInfo(SpellIds.LightningBolt, SpellIds.LightningBoltOverload, SpellIds.ElementalBlast, SpellIds.ElementalBlastOverload, SpellIds.Icefury, SpellIds.IcefuryOverload, - SpellIds.LavaBurst, SpellIds.LavaBurstOverload, SpellIds.ChainLightning, SpellIds.ChainLightningOverload, SpellIds.LavaBeam, SpellIds.LavaBeamOverload, SpellIds.Stormkeeper); + if (targets.Targets == null) + return; + + targets.Targets.Update(caster); + + CastSpellExtraArgs args = new(); + args.OriginalCastId = originalCastId; + caster.CastSpell(targets, overloadSpellId, args); + }, TimeSpan.FromSeconds(400)); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } + + static uint GetTriggeredSpellId(uint triggeringSpellId) + { + switch (triggeringSpellId) + { + case SpellIds.LightningBolt: return SpellIds.LightningBoltOverload; + case SpellIds.ElementalBlast: return SpellIds.ElementalBlastOverload; + case SpellIds.Icefury: return SpellIds.IcefuryOverload; + case SpellIds.LavaBurst: return SpellIds.LavaBurstOverload; + case SpellIds.ChainLightning: return SpellIds.ChainLightningOverload; + default: + break; } + return 0; + } +} - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) +// 45284 - Lightning Bolt Overload +// 45297 - Chain Lightning Overload +// 114738 - Lava Beam Overload +// 120588 - Elemental Blast Overload +// 219271 - Icefury Overload +[Script] // 285466 - Lava Burst Overload +class spell_sha_mastery_elemental_overload_proc : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MasteryElementalOverload); + } + + void ApplyDamageModifier(uint effIndex) + { + AuraEffect elementalOverload = GetCaster().GetAuraEffect(SpellIds.MasteryElementalOverload, 1); + if (elementalOverload != null) + SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), elementalOverload.GetAmount())); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(ApplyDamageModifier, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 334033 - Molten Assault (60103 - Lava Lash) +class spell_sha_molten_assault : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlameShock); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.MoltenAssault); + } + + void TriggerFlameShocks(uint effIndex) + { + Unit caster = GetCaster(); + Unit lavaLashTarget = GetHitUnit(); + if (!lavaLashTarget.HasAura(SpellIds.FlameShock, caster.GetGUID())) + return; + + float range = 10.0f; + List targets = new(); + WorldObjectSpellAreaTargetCheck check = new(range, lavaLashTarget, caster, caster, Global.SpellMgr.GetSpellInfo(SpellIds.FlameShock, Difficulty.None), + SpellTargetCheckTypes.Enemy, null, SpellTargetObjectTypes.Unit, WorldObjectSpellAreaTargetSearchReason.Area); + WorldObjectListSearcher searcher = new(caster, targets, check, GridMapTypeMask.Creature | GridMapTypeMask.Player); + Cell.VisitAllObjects(lavaLashTarget, searcher, range + SharedConst.ExtraCellSearchRadius); + + var predicate = new UnitAuraCheck(true, SpellIds.FlameShock, GetCaster().GetGUID()).Invoke; + targets.PartitionInPlace(predicate); + + var withoutFlameShockIndex = targets.FindIndex(0, x => !predicate(x)); + if (withoutFlameShockIndex != -1) + targets.RandomShuffle(withoutFlameShockIndex, targets.Count - withoutFlameShockIndex); + + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress); + args.SetTriggeringSpell(GetSpell()); + + // targets that already have flame shock are first in the list (and need to refresh it) + for (var i = 0; i < Math.Min(targets.Count, GetEffectValue() + 1); ++i) + caster.CastSpell(targets[i], SpellIds.FlameShock, args); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(TriggerFlameShocks, 2, SpellEffectName.Dummy)); + } +} + +[Script] // 469344 Molten Thunder +class spell_sha_molten_thunder : AuraScript +{ + public int ProcCount = 0; + + public override void Register() { } +} + +[Script] +class spell_sha_molten_thunder_sundering : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MoltenThunderTalent, SpellIds.MoltenThunderProc); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.MoltenThunderTalent); + } + + void RemoveIncapacitateEffect(List targets) + { + targets.Clear(); + } + + void RollReset() + { + Unit shaman = GetCaster(); + Aura talent = shaman.GetAura(SpellIds.MoltenThunderTalent); + if (talent == null) + return; + + AuraEffect chanceBaseEffect = talent.GetEffect(1); + AuraEffect chancePerTargetEffect = talent.GetEffect(2); + AuraEffect targetLimitEffect = talent.GetEffect(3); + if (chanceBaseEffect == null || chancePerTargetEffect == null || targetLimitEffect == null) + return; + + spell_sha_molten_thunder counterScript = talent.GetScript(); + if (counterScript == null) + return; + + int procChance = chanceBaseEffect.GetAmount(); + procChance += (int)Math.Min(targetLimitEffect.GetAmount(), GetUnitTargetCountForEffect(0)) * chancePerTargetEffect.GetAmount(); + procChance >>= counterScript.ProcCount; // Each consecutive reset reduces these chances by half + if (RandomHelper.randChance(procChance)) { - SpellInfo spellInfo = eventInfo.GetSpellInfo(); - if (spellInfo == null || eventInfo.GetProcSpell() == null) - return false; - - if (GetTriggeredSpellId(spellInfo.Id) == 0) - return false; - - float chance = aurEff.GetAmount(); // Mastery % amount - - if (spellInfo.Id == SpellIds.ChainLightning) - chance /= 3.0f; - - Aura stormkeeper = eventInfo.GetActor().GetAura(SpellIds.Stormkeeper); - if (stormkeeper != null) - if (eventInfo.GetProcSpell().m_appliedMods.Contains(stormkeeper)) - chance = 100.0f; - - return RandomHelper.randChance(chance); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - PreventDefaultAction(); - - Unit caster = procInfo.GetActor(); - - var targets = new CastSpellTargetArg(procInfo.GetProcTarget()); - var overloadSpellId = GetTriggeredSpellId(procInfo.GetSpellInfo().Id); - var originalCastId = procInfo.GetProcSpell().m_castId; - caster.m_Events.AddEventAtOffset(() => + shaman.CastSpell(shaman, SpellIds.MoltenThunderProc, new CastSpellExtraArgs() { - if (targets.Targets == null) - return; - - targets.Targets.Update(caster); - - CastSpellExtraArgs args = new(); - args.OriginalCastId = originalCastId; - caster.CastSpell(targets, overloadSpellId, args); - }, TimeSpan.FromMilliseconds(400)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + shaman.GetSpellHistory().ResetCooldown(GetSpellInfo().Id, true); + ++counterScript.ProcCount; } + else + counterScript.ProcCount = 0; + } - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(RemoveIncapacitateEffect, 3, Targets.UnitRectCasterEnemy)); + AfterCast.Add(new(RollReset)); + } +} - uint GetTriggeredSpellId(uint triggeringSpellId) +[Script] // 30884 - Nature's Guardian +class spell_sha_natures_guardian : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.NaturesGuardianCooldown); + } + + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return eventInfo.GetActionTarget().HealthBelowPct(aurEff.GetAmount()) + && !eventInfo.GetActionTarget().HasAura(SpellIds.NaturesGuardianCooldown); + } + + static void StartCooldown(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit shaman = eventInfo.GetActionTarget(); + shaman.CastSpell(shaman, SpellIds.NaturesGuardianCooldown, new CastSpellExtraArgs() { - switch (triggeringSpellId) + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(StartCooldown, 0, AuraType.Dummy)); + } +} + +[Script] // 210621 - Path of Flames Spread +class spell_sha_path_of_flames_spread : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlameShock); + } + + void FilterTargets(List targets) + { + targets.Remove(GetExplTargetUnit()); + targets.RandomResize(new UnitAuraCheck(false, SpellIds.FlameShock, GetCaster().GetGUID()).Invoke, 1); + } + + void HandleScript(uint effIndex) + { + Unit mainTarget = GetExplTargetUnit(); + if (mainTarget != null) + { + Aura flameShock = mainTarget.GetAura(SpellIds.FlameShock, GetCaster().GetGUID()); + if (flameShock != null) { - case SpellIds.LightningBolt: - return SpellIds.LightningBoltOverload; - case SpellIds.ElementalBlast: - return SpellIds.ElementalBlastOverload; - case SpellIds.Icefury: - return SpellIds.IcefuryOverload; - case SpellIds.LavaBurst: - return SpellIds.LavaBurstOverload; - case SpellIds.ChainLightning: - return SpellIds.ChainLightningOverload; - case SpellIds.LavaBeam: - return SpellIds.LavaBeamOverload; - default: - break; - } - return 0; - } - } - - // 45284 - Lightning Bolt Overload - // 45297 - Chain Lightning Overload - // 114738 - Lava Beam Overload - // 120588 - Elemental Blast Overload - // 219271 - Icefury Overload - [Script] // 285466 - Lava Burst Overload - class spell_sha_mastery_elemental_overload_proc : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.MasteryElementalOverload); - } - - void ApplyDamageModifier(uint effIndex) - { - AuraEffect elementalOverload = GetCaster().GetAuraEffect(SpellIds.MasteryElementalOverload, 1); - if (elementalOverload != null) - SetHitDamage(MathFunctions.CalculatePct(GetHitDamage(), elementalOverload.GetAmount())); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(ApplyDamageModifier, 0, SpellEffectName.SchoolDamage)); - } - } - - [Script] // 30884 - Nature's Guardian - class spell_sha_natures_guardian : AuraScript - { - bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - return eventInfo.GetActionTarget().HealthBelowPct(aurEff.GetAmount()); - } - - public override void Register() - { - DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell)); - } - } - - [Script] // 210621 - Path of Flames Spread - class spell_sha_path_of_flames_spread : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.FlameShock); - } - - void FilterTargets(List targets) - { - targets.Remove(GetExplTargetUnit()); - targets.RandomResize(target => target.GetTypeId() == TypeId.Unit && !target.ToUnit().HasAura(SpellIds.FlameShock, GetCaster().GetGUID()), 1); - } - - void HandleScript(uint effIndex) - { - Unit mainTarget = GetExplTargetUnit(); - if (mainTarget != null) - { - Aura flameShock = mainTarget.GetAura(SpellIds.FlameShock, GetCaster().GetGUID()); - if (flameShock != null) + Aura newAura = GetCaster().AddAura(SpellIds.FlameShock, GetHitUnit()); + if (newAura != null) { - Aura newAura = GetCaster().AddAura(SpellIds.FlameShock, GetHitUnit()); - if (newAura != null) - { - newAura.SetDuration(flameShock.GetDuration()); - newAura.SetMaxDuration(flameShock.GetDuration()); - } + newAura.SetDuration(flameShock.GetDuration()); + newAura.SetMaxDuration(flameShock.GetDuration()); } } } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); - OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.Dummy)); - } } - // 114083 - Restorative Mists - [Script] // 294020 - Restorative Mists - class spell_sha_restorative_mists : SpellScript + public override void Register() { - int _targetCount; + OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy)); + OnEffectHitTarget.Add(new(HandleScript, 1, SpellEffectName.Dummy)); + } +} - void FilterTargets(List targets) - { - _targetCount = targets.Count; - } - - void HandleHeal(uint effIndex) - { - if (_targetCount != 0) - SetHitHeal(GetHitHeal() / _targetCount); - } - - public override void Register() - { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaAlly)); - OnEffectHitTarget.Add(new(HandleHeal, 0, SpellEffectName.Heal)); - } +[Script] // 375982 - Primordial Wave +class spell_sha_primordial_wave : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FlameShock, SpellIds.PrimordialWaveDamage); } - // 2645 - Ghost Wolf - [Script] // 260878 - Spirit Wolf - class spell_sha_spirit_wolf : AuraScript + void TriggerDamage(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GhostWolf, SpellIds.SpiritWolfTalent, SpellIds.SpiritWolfPeriodic, SpellIds.SpiritWolfAura); - } + Unit shaman = GetCaster(); + List targets = new(); + FireNovaTargetCheck check = new() { MaxSearchRange = GetSpell().GetMinMaxRange(false).maxRange, Shaman = shaman }; + UnitListSearcher searcher = new(shaman, targets, check); + Cell.VisitAllObjects(shaman, searcher, check.MaxSearchRange); - void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - if (target.HasAura(SpellIds.SpiritWolfTalent) && target.HasAura(SpellIds.GhostWolf)) - target.CastSpell(target, SpellIds.SpiritWolfPeriodic, aurEff); - } + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + args.SetTriggeringSpell(GetSpell()); - void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - GetTarget().RemoveAurasDueToSpell(SpellIds.SpiritWolfPeriodic); - GetTarget().RemoveAurasDueToSpell(SpellIds.SpiritWolfAura); - } - - public override void Register() - { - AfterEffectApply.Add(new(OnApply, 0, AuraType.Any, AuraEffectHandleModes.Real)); - AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Any, AuraEffectHandleModes.Real)); - } + foreach (Unit target in targets) + shaman.CastSpell(target, SpellIds.PrimordialWaveDamage, args); } - [Script] // 51564 - Tidal Waves - class spell_sha_tidal_waves : AuraScript + void PreventLavaSurge(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.TidalWaves); - } - - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, -aurEff.GetAmount()); - args.AddSpellMod(SpellValueMod.BasePoint1, aurEff.GetAmount()); - - GetTarget().CastSpell(GetTarget(), SpellIds.TidalWaves, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } + PreventHitDefaultEffect(effIndex); } - [Script] // 28823 - Totemic Power - class spell_sha_t3_6p_bonus : AuraScript + void EnergizeMaelstrom(uint effIndex) { - public override bool Validate(SpellInfo spellInfo) + spell_sha_maelstrom_weapon_base.GenerateMaelstromWeapon(GetCaster(), GetEffectValue()); + } + + public override void Register() + { + ChrSpecialization specialization = ChrSpecialization.None; + Spell spell = GetSpell(); + if (spell != null) // spell doesn't exist at startup validation { - return ValidateSpellInfo(SpellIds.TotemicPowerArmor, SpellIds.TotemicPowerAttackPower, SpellIds.TotemicPowerSpellPower, SpellIds.TotemicPowerMp5); + Player caster = spell.GetCaster()?.ToPlayer(); + if (caster != null) + specialization = caster.GetPrimarySpecialization(); } - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); + OnEffectHitTarget.Add(new(TriggerDamage, 0, SpellEffectName.Dummy)); - uint spellId; - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); + if (specialization != ChrSpecialization.ShamanElemental) + OnEffectLaunch.Add(new(PreventLavaSurge, 5, SpellEffectName.TriggerSpell)); - switch (target.GetClass()) + if (specialization == ChrSpecialization.None || specialization == ChrSpecialization.ShamanEnhancement) + OnEffectHitTarget.Add(new(EnergizeMaelstrom, 4, SpellEffectName.Dummy)); + } +} + +// 114083 - Restorative Mists +[Script] // 294020 - Restorative Mists +class spell_sha_restorative_mists : SpellScript +{ + void HandleHeal(uint effIndex) + { + SetHitHeal((int)(GetHitHeal() / GetUnitTargetCountForEffect(effIndex))); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHeal, 0, SpellEffectName.Heal)); + } +} + +// 2645 - Ghost Wolf +// 260878 - Spirit Wolf +class spell_sha_spirit_wolf : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GhostWolf, SpellIds.SpiritWolfTalent, SpellIds.SpiritWolfPeriodic, SpellIds.SpiritWolfAura); + } + + void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + if (target.HasAura(SpellIds.SpiritWolfTalent) && target.HasAura(SpellIds.GhostWolf)) + target.CastSpell(target, SpellIds.SpiritWolfPeriodic, new CastSpellExtraArgs() { - case Class.Paladin: - case Class.Priest: - case Class.Shaman: - case Class.Druid: - spellId = SpellIds.TotemicPowerMp5; - break; - case Class.Mage: - case Class.Warlock: - spellId = SpellIds.TotemicPowerSpellPower; - break; - case Class.Hunter: - case Class.Rogue: - spellId = SpellIds.TotemicPowerAttackPower; - break; - case Class.Warrior: - spellId = SpellIds.TotemicPowerArmor; - break; - default: - return; - } - - caster.CastSpell(target, spellId, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff + }); } - [Script] // 28820 - Lightning Shield - class spell_sha_t3_8p_bonus : AuraScript + void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode) { - void PeriodicTick(AuraEffect aurEff) - { - PreventDefaultAction(); - - // Need Remove self if Lightning Shield not active - if (GetTarget().GetAuraEffect(AuraType.ProcTriggerSpell, SpellFamilyNames.Shaman, new FlagArray128(0x400), GetCaster().GetGUID()) == null) - Remove(); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 1, AuraType.PeriodicTriggerSpell)); - } + GetTarget().RemoveAurasDueToSpell(SpellIds.SpiritWolfPeriodic); + GetTarget().RemoveAurasDueToSpell(SpellIds.SpiritWolfAura); } - [Script] // 64928 - Item - Shaman T8 Elemental 4P Bonus - class spell_sha_t8_elemental_4p_bonus : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.Electrified); - } + AfterEffectApply.Add(new(OnApply, 0, AuraType.Any, AuraEffectHandleModes.Real)); + AfterEffectRemove.Add(new(OnRemove, 0, AuraType.Any, AuraEffectHandleModes.Real)); + } +} - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); +[Script] // 319930 - Stormblast +class spell_sha_stormblast : AuraScript +{ + public ObjectGuid AllowedOriginalCastId; - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; + public override void Register() { } +} - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.Electrified, GetCastDifficulty()); - int amount = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount()); - - Cypher.Assert(spellInfo.GetMaxTicks() > 0); - amount /= (int)spellInfo.GetMaxTicks(); - - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(target, SpellIds.Electrified, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 470466 - Stormblast (Stormstrike and Winstrike damaging spells) +class spell_sha_stormblast_damage : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.StormblastTalent, 0), (SpellIds.EnhancedElements, 0)); } - [Script] // 67228 - Item - Shaman T9 Elemental 4P Bonus (Lava Burst) - class spell_sha_t9_elemental_4p_bonus : AuraScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) + Aura stormblast = GetCaster().GetAura(SpellIds.StormblastTalent); + if (stormblast != null) { - return ValidateSpellInfo(SpellIds.LavaBurstBonusDamage); + spell_sha_stormblast script = stormblast.GetScript(); + if (script != null) + return script.AllowedOriginalCastId == GetSpell().m_originalCastId; } - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.LavaBurstBonusDamage, GetCastDifficulty()); - int amount = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount()); - - Cypher.Assert(spellInfo.GetMaxTicks() > 0); - amount /= (int)spellInfo.GetMaxTicks(); - - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(target, SpellIds.LavaBurstBonusDamage, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } + return false; } - [Script] // 70817 - Item - Shaman T10 Elemental 4P Bonus - class spell_sha_t10_elemental_4p_bonus : AuraScript + void TriggerDamage() { - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + AuraEffect stormblast = GetCaster().GetAuraEffect(SpellIds.StormblastTalent, 0); + if (stormblast != null) { - PreventDefaultAction(); + int damage = MathFunctions.CalculatePct(GetHitDamage(), stormblast.GetAmount()); - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); + // Not part of SpellFamilyFlags for mastery effect but known to be affected by it + AuraEffect mastery = GetCaster().GetAuraEffect(SpellIds.EnhancedElements, 0); + if (mastery != null) + MathFunctions.AddPct(ref damage, mastery.GetAmount()); - // try to find spell Flame Shock on the target - AuraEffect flameShock = target.GetAuraEffect(AuraType.PeriodicDamage, SpellFamilyNames.Shaman, new FlagArray128(0x10000000), caster.GetGUID()); - if (flameShock == null) - return; - - Aura flameShockAura = flameShock.GetBase(); - - int maxDuration = flameShockAura.GetMaxDuration(); - int newDuration = flameShockAura.GetDuration() + aurEff.GetAmount() * Time.InMilliseconds; - - flameShockAura.SetDuration(newDuration); - // is it blizzlike to change max duration for Fs? - if (newDuration > maxDuration) - flameShockAura.SetMaxDuration(newDuration); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 70808 - Item - Shaman T10 Restoration 4P Bonus - class spell_sha_t10_restoration_4p_bonus : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ChainedHeal); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - HealInfo healInfo = eventInfo.GetHealInfo(); - if (healInfo == null || healInfo.GetHeal() == 0) - return; - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.ChainedHeal, GetCastDifficulty()); - int amount = (int)MathFunctions.CalculatePct(healInfo.GetHeal(), aurEff.GetAmount()); - - Cypher.Assert(spellInfo.GetMaxTicks() > 0); - amount /= (int)spellInfo.GetMaxTicks(); - - Unit caster = eventInfo.GetActor(); - Unit target = eventInfo.GetProcTarget(); - - CastSpellExtraArgs args = new(aurEff); - args.AddSpellMod(SpellValueMod.BasePoint0, amount); - caster.CastSpell(target, SpellIds.ChainedHeal, args); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 260895 - Unlimited Power - class spell_sha_unlimited_power : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.UnlimitedPowerBuff); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) - { - Unit caster = procInfo.GetActor(); - Aura aura = caster.GetAura(SpellIds.UnlimitedPowerBuff); - if (aura != null) - aura.SetStackAmount((byte)(aura.GetStackAmount() + 1)); - else - caster.CastSpell(caster, SpellIds.UnlimitedPowerBuff, procInfo.GetProcSpell()); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } - } - - [Script] // 200071 - Undulation - class spell_sha_undulation_passive : AuraScript - { - byte _castCounter = 1; // first proc happens after two casts, then one every 3 casts - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.UndulationProc); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - if (++_castCounter == 3) + GetCaster().CastSpell(GetHitUnit(), SpellIds.StormblastDamage, new CastSpellExtraArgs() { - GetTarget().CastSpell(GetTarget(), SpellIds.UndulationProc, true); - _castCounter = 0; - } - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, damage) } + }); } } - [Script] // 33757 - Windfury Weapon - class spell_sha_windfury_weapon : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + AfterHit.Add(new(TriggerDamage)); + } +} + +[Script] // 470466 - Stormblast (17364 - Stormstrike, 115356 - Windstrike) +class spell_sha_stormblast_proc : SpellScript +{ + public override bool Load() + { + Unit caster = GetCaster(); + return caster.HasAura(SpellIds.StormblastTalent) + && caster.HasAura(SpellIds.StormblastProc); + } + + // Store allowed CastId in passive aura because damaging spells are delayed (and delayed further if Stormflurry is triggered) + void SaveCastId() + { + Unit caster = GetCaster(); + Aura stormblast = caster.GetAura(SpellIds.StormblastTalent); + if (stormblast != null) { - return ValidateSpellInfo(SpellIds.WindfuryEnchantment); + spell_sha_stormblast script = stormblast.GetScript(); + if (script != null) + script.AllowedOriginalCastId = GetSpell().m_castId; } - public override bool Load() + caster.RemoveAuraFromStack(SpellIds.StormblastProc); + } + + public override void Register() + { + OnCast.Add(new(SaveCastId)); + } +} + +class StormflurryEvent : BasicEvent +{ + Unit _caster; + CastSpellTargetArg _target; + ObjectGuid _originalCastId; + int _damagePercent; + uint _mainHandDamageSpellId; + uint _offHandDamageSpellId; + int _procChance; + + public StormflurryEvent(Unit caster, Unit target, ObjectGuid originalCastId, int damagePercent, uint mainHandDamageSpellId, uint offHandDamageSpellId, int procChance) + { + _caster = caster; + _target = target; + _originalCastId = originalCastId; + _damagePercent = damagePercent; + _mainHandDamageSpellId = mainHandDamageSpellId; + _offHandDamageSpellId = offHandDamageSpellId; + _procChance = procChance; + } + + public override bool Execute(ulong time, uint diff) + { + if (_target.Targets == null) + return true; + + _target.Targets.Update(_caster); + + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError; + args.OriginalCastId = _originalCastId; + args.CustomArg = new Data() { DamagePercent = _damagePercent }; + + _caster.CastSpell(_target, _mainHandDamageSpellId, args); + _caster.CastSpell(_target, _offHandDamageSpellId, args); + + if (!RandomHelper.randChance(_procChance)) + return true; + + _caster.m_Events.AddEvent(this, TimeSpan.FromSeconds(time) + TimeSpan.FromSeconds(200)); + return false; + } + + public class Data + { + public int DamagePercent; + } +} + +// 198367 Stormflurry +// 344357 Stormflurry +[Script("spell_sha_artifact_stormflurry_stormstrike", SpellIds.StormflurryArtifact, SpellIds.StormstrikeDamageMainHand, SpellIds.StormstrikeDamageOffHand)] +[Script("spell_sha_artifact_stormflurry_windstrike", SpellIds.StormflurryArtifact, SpellIds.WindstrikeDamageMainHand, SpellIds.WindstrikeDamageOffHand)] +[Script("spell_sha_stormflurry_stormstrike", SpellIds.Stormflurry, SpellIds.StormstrikeDamageMainHand, SpellIds.StormstrikeDamageOffHand)] +[Script("spell_sha_stormflurry_windstrike", SpellIds.Stormflurry, SpellIds.WindstrikeDamageMainHand, SpellIds.WindstrikeDamageOffHand)] +class spell_sha_stormflurry : SpellScript +{ + uint _stormflurrySpellId; + uint _mainHandDamageSpellId; + uint _offHandDamageSpellId; + + public spell_sha_stormflurry(uint stormflurrySpellId, uint mainHandDamageSpellId, uint offHandDamageSpellId) + { + _stormflurrySpellId = stormflurrySpellId; + _mainHandDamageSpellId = mainHandDamageSpellId; + _offHandDamageSpellId = offHandDamageSpellId; + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(_stormflurrySpellId, _mainHandDamageSpellId, _offHandDamageSpellId) + && ValidateSpellEffect((spellInfo.Id, 1)) + && spellInfo.GetEffect(0).IsEffect(SpellEffectName.TriggerSpell) + && spellInfo.GetEffect(1).IsEffect(SpellEffectName.TriggerSpell); + } + + public override bool Load() + { + return GetCaster().HasAura(_stormflurrySpellId); + } + + void HandleProc(uint effIndex) + { + Unit caster = GetCaster(); + Aura stormflurry = caster.GetAura(_stormflurrySpellId); + if (stormflurry == null) + return; + + AuraEffect chanceEffect = stormflurry.GetEffect(0); + AuraEffect damageEffect = stormflurry.GetEffect(1); + if (chanceEffect == null || damageEffect == null) + return; + + int procChance = chanceEffect.GetAmount(); + if (!RandomHelper.randChance(procChance)) + return; + + caster.m_Events.AddEventAtOffset(new StormflurryEvent(caster, GetHitUnit(), GetSpell().m_castId, damageEffect.GetAmount(), + _mainHandDamageSpellId, _offHandDamageSpellId, procChance), TimeSpan.FromSeconds(200)); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleProc, 1, SpellEffectName.TriggerSpell)); + } +} + +// 32175 - Stormstrike +[Script] // 32176 - Stormstrike Off-Hand +class spell_sha_stormflurry_damage : SpellScript +{ + public override bool Load() + { + return GetSpell().m_customArg.GetType() == typeof(StormflurryEvent.Data); + } + + void ApplyModifier(SpellEffectInfo effectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + MathFunctions.ApplyPct(ref pctMod, ((StormflurryEvent.Data)GetSpell().m_customArg).DamagePercent); + } + + public override void Register() + { + CalcDamage.Add(new(ApplyModifier)); + } +} + +[Script] // 201845 - Stormsurge +class spell_sha_stormsurge : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StormsurgeProc); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.StormsurgeProc, new CastSpellExtraArgs() { - return GetCaster().IsPlayer(); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 187881 - Maelstrom Weapon +class spell_sha_stormweaver : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StormweaverPvpTalent); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.StormweaverPvpTalent); + } + + void PreventAffectingHealingSpells(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(PreventAffectingHealingSpells, 2, Targets.UnitCaster)); + OnObjectTargetSelect.Add(new(PreventAffectingHealingSpells, 4, Targets.UnitCaster)); + } +} + +[Script] // 384359 - Swirling Maelstrom +class spell_sha_swirling_maelstrom : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)) + && spell_sha_maelstrom_weapon_base.Validate(); + } + + bool CheckHailstormProc(ProcEventInfo eventInfo) + { + if (eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Shaman, new FlagArray128(0x80000000, 0x0, 0x0, 0x0))) // Frost Shock + { + Aura hailstorm = eventInfo.GetActor().GetAura(SpellIds.HailstormBuff); + if (hailstorm == null || hailstorm.GetStackAmount() < GetEffect(1).GetAmount()) + return false; + + if (!eventInfo.GetProcSpell().m_appliedMods.Contains(hailstorm)) + return false; } - void HandleEffect(uint effIndex) - { - PreventHitDefaultEffect(effIndex); + return true; + } - Item mainHand = GetCaster().ToPlayer().GetWeaponForAttack(WeaponAttackType.BaseAttack, false); - if (mainHand != null) - GetCaster().CastSpell(mainHand, SpellIds.WindfuryEnchantment, GetSpell()); - } + void EnergizeMaelstrom(AuraEffect aurEff, ProcEventInfo eventInfo) + { + spell_sha_maelstrom_weapon_base.GenerateMaelstromWeapon(GetTarget(), aurEff.GetAmount()); + } - public override void Register() + public override void Register() + { + DoCheckProc.Add(new(CheckHailstormProc)); + OnEffectProc.Add(new(EnergizeMaelstrom, 0, AuraType.Dummy)); + } +} + +[Script] // 384444 - Thorim's Invocation +class spell_sha_thorims_invocation : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LightningBolt, SpellIds.ChainLightning); + } + + public override void Register() + { + } + + public + uint SpellIdToTrigger = SpellIds.LightningBolt; +} + +// 188196 - Lightning Bolt +// 188443 - Chain Lightning +[Script] // 452201 - Tempest +class spell_sha_thorims_invocation_primer : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ThorimsInvocation, SpellIds.LightningBolt, SpellIds.ChainLightning) + && ValidateSpellEffect((spellInfo.Id, 0)) + && spellInfo.GetEffect(0).IsEffect(SpellEffectName.SchoolDamage); + } + + void UpdateThorimsInvocationSpell() + { + Aura thorimsInvocation = GetCaster().GetAura(SpellIds.ThorimsInvocation); + if (thorimsInvocation != null) { - OnEffectHitTarget.Add(new(HandleEffect, 0, SpellEffectName.Dummy)); + spell_sha_thorims_invocation spellIdHolder = thorimsInvocation.GetScript(); + if (spellIdHolder != null) + spellIdHolder.SpellIdToTrigger = GetUnitTargetCountForEffect(0) > 1 ? SpellIds.ChainLightning : SpellIds.LightningBolt; } } - [Script] // 319773 - Windfury Weapon (proc) - class spell_sha_windfury_weapon_proc : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.WindfuryAttack); - } + AfterCast.Add(new(UpdateThorimsInvocationSpell)); + } +} - void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - for (uint i = 0; i < 2; ++i) - eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.WindfuryAttack, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); - } +[Script] // 115357 - Windstrike (Mh) +class spell_sha_thorims_invocation_trigger : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.ThorimsInvocation, 0)); } - [Script] // 378269 - Windspeaker's Lava Resurgence - class spell_sha_windspeakers_lava_resurgence : SpellScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.VolcanicSurge); - } - - void PreventLavaSurge(uint effIndex) - { - if (GetCaster().HasAura(SpellIds.VolcanicSurge)) - PreventHitDefaultEffect(effIndex); - } - - void PreventVolcanicSurge(uint effIndex) - { - if (!GetCaster().HasAura(SpellIds.VolcanicSurge)) - PreventHitDefaultEffect(effIndex); - } - - public override void Register() - { - OnEffectLaunch.Add(new(PreventLavaSurge, 1, SpellEffectName.TriggerSpell)); - OnEffectLaunch.Add(new(PreventVolcanicSurge, 2, SpellEffectName.TriggerSpell)); - } + return GetCaster().HasAura(SpellIds.ThorimsInvocation); } - // 192078 - Wind Rush Totem (Spell) - [Script] // 12676 - AreaTriggerId - class areatrigger_sha_wind_rush_totem : AreaTriggerAI + void TriggerLightningSpell(uint effIndex) { - uint RefreshTime = 4500; + Unit caster = GetCaster(); - uint _refreshTimer; + AuraEffect thorimsInvocation = caster.GetAuraEffect(SpellIds.ThorimsInvocation, 0); + if (thorimsInvocation == null) + return; - public areatrigger_sha_wind_rush_totem(AreaTrigger areatrigger) : base(areatrigger) + spell_sha_thorims_invocation spellIdHolder = thorimsInvocation.GetBase().GetScript(); + if (spellIdHolder == null) + return; + + var (spellInfo, triggerFlags) = caster.GetCastSpellInfo(Global.SpellMgr.GetSpellInfo(spellIdHolder.SpellIdToTrigger, GetCastDifficulty())); + + // Remove Overflowing Maelstrom spellmod early to make next cast behave as if it consumed only 5 or less maelstrom stacks + // this works because consuming "up to 5 stacks" will always cause Maelstrom Weapon stacks to drop to 5 or lower + // which means Overflowing Maelstrom needs removing anyway + caster.RemoveAurasDueToSpell(SpellIds.OverflowingMaelstromAura); + + caster.CastSpell(GetHitUnit(), spellInfo.Id, new CastSpellExtraArgs() { - _refreshTimer = RefreshTime; - } + TriggerFlags = triggerFlags | TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.IgnoreCastTime | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); - public override void OnUpdate(uint diff) + // Manually remove stacks - Maelstrom Weapon aura cannot proc from procs and free Lightning Bolt/Chain Lightning procs from Arc Discharge (455096) shoulnd't consume it + Aura maelstromWeaponVisibleAura = caster.GetAura(SpellIds.MaelstromWeaponVisibleAura); + if (maelstromWeaponVisibleAura != null) + spell_sha_maelstrom_weapon_base.ConsumeMaelstromWeapon(caster, maelstromWeaponVisibleAura, thorimsInvocation.GetAmount()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(TriggerLightningSpell, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 51564 - Tidal Waves +class spell_sha_tidal_waves : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TidalWaves); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + GetTarget().CastSpell(GetTarget(), SpellIds.TidalWaves, new CastSpellExtraArgs() { - _refreshTimer -= diff; - if (_refreshTimer <= 0) + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff, + SpellValueOverrides = { - Unit caster = at.GetCaster(); - if (caster != null) - { - foreach (ObjectGuid guid in at.GetInsideUnits()) - { - Unit unit = ObjAccessor.GetUnit(caster, guid); - if (unit != null) - { - if (!caster.IsFriendlyTo(unit)) - continue; - - caster.CastSpell(unit, SpellIds.WindRush, true); - } - } - } - _refreshTimer += RefreshTime; + new( SpellValueMod.BasePoint0, -aurEff.GetAmount() ), + new(SpellValueMod.BasePoint1, aurEff.GetAmount() ) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +[Script] // 28823 - Totemic Power +class spell_sha_t3_6p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.TotemicPowerArmor, SpellIds.TotemicPowerAttackPower, SpellIds.TotemicPowerSpellPower, SpellIds.TotemicPowerMP5); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + uint spellId; + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + switch (target.GetClass()) + { + case Class.Paladin: + case Class.Priest: + case Class.Shaman: + case Class.Druid: + spellId = SpellIds.TotemicPowerMP5; + break; + case Class.Mage: + case Class.Warlock: + spellId = SpellIds.TotemicPowerSpellPower; + break; + case Class.Hunter: + case Class.Rogue: + spellId = SpellIds.TotemicPowerAttackPower; + break; + case Class.Warrior: + spellId = SpellIds.TotemicPowerArmor; + break; + default: + return; } - public override void OnUnitEnter(Unit unit) + caster.CastSpell(target, spellId, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 28820 - Lightning Shield +class spell_sha_t3_8p_bonus : AuraScript +{ + void PeriodicTick(AuraEffect aurEff) + { + PreventDefaultAction(); + + // Need remove self if Lightning Shield not active + if (GetTarget().GetAuraEffect(AuraType.ProcTriggerSpell, SpellFamilyNames.Shaman, new FlagArray128(0x400), GetCaster().GetGUID()) == null) + Remove(); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(PeriodicTick, 1, AuraType.PeriodicTriggerSpell)); + } +} + +[Script] // 64928 - Item - Shaman T8 Elemental 4P Bonus +class spell_sha_t8_elemental_4p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Electrified); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.Electrified, GetCastDifficulty()); + int amount = MathFunctions.CalculatePct((int)(damageInfo.GetDamage()), aurEff.GetAmount()); + + Cypher.Assert(spellInfo.GetMaxTicks() > 0); + amount /= (int)spellInfo.GetMaxTicks(); + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + caster.CastSpell(target, SpellIds.Electrified, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, amount) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 67228 - Item - Shaman T9 Elemental 4P Bonus (Lava Burst) +class spell_sha_t9_elemental_4p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.LavaBurstBonusDamage); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.LavaBurstBonusDamage, GetCastDifficulty()); + int amount = MathFunctions.CalculatePct((int)(damageInfo.GetDamage()), aurEff.GetAmount()); + + Cypher.Assert(spellInfo.GetMaxTicks() > 0); + amount /= (int)spellInfo.GetMaxTicks(); + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + caster.CastSpell(target, SpellIds.LavaBurstBonusDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, amount) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 70817 - Item - Shaman T10 Elemental 4P Bonus +class spell_sha_t10_elemental_4p_bonus : AuraScript +{ + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + // try to find spell Flame Shock on the target + AuraEffect flameShock = target.GetAuraEffect(AuraType.PeriodicDamage, SpellFamilyNames.Shaman, new FlagArray128(0x10000000), caster.GetGUID()); + if (flameShock == null) + return; + + Aura flameShockAura = flameShock.GetBase(); + + int maxDuration = flameShockAura.GetMaxDuration(); + int newDuration = flameShockAura.GetDuration() + aurEff.GetAmount() * Time.InMilliseconds; + + flameShockAura.SetDuration(newDuration); + // is it blizzlike to change max duration for Fs? + if (newDuration > maxDuration) + flameShockAura.SetMaxDuration(newDuration); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 70808 - Item - Shaman T10 Restoration 4P Bonus +class spell_sha_t10_restoration_4p_bonus : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChainedHeal); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + HealInfo healInfo = eventInfo.GetHealInfo(); + if (healInfo == null || healInfo.GetHeal() == 0) + return; + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.ChainedHeal, GetCastDifficulty()); + int amount = MathFunctions.CalculatePct((int)(healInfo.GetHeal()), aurEff.GetAmount()); + + Cypher.Assert(spellInfo.GetMaxTicks() > 0); + amount /= (int)spellInfo.GetMaxTicks(); + + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetProcTarget(); + + caster.CastSpell(target, SpellIds.ChainedHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringAura = aurEff, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, amount) } + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 260895 - Unlimited Power +class spell_sha_unlimited_power : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UnlimitedPowerBuff); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + Unit caster = procInfo.GetActor(); + Aura aura = caster.GetAura(SpellIds.UnlimitedPowerBuff); + if (aura != null) + aura.SetStackAmount((byte)(aura.GetStackAmount() + 1)); + else + caster.CastSpell(caster, SpellIds.UnlimitedPowerBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringSpell = procInfo.GetProcSpell() + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 200071 - Undulation +class spell_sha_undulation_passive : AuraScript +{ + byte _castCounter = 1; // first proc happens after two casts, then one every 3 casts + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UndulationProc); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + if (++_castCounter == 3) + { + GetTarget().CastSpell(GetTarget(), SpellIds.UndulationProc, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + _castCounter = 0; + } + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 470490 - Unrelenting Storms +class spell_sha_unrelenting_storms : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UnrelentingStormsReduction) + && ValidateSpellEffect((SpellIds.UnrelentingStormsTalent, 1)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.UnrelentingStormsTalent); + } + + void Trigger(uint effIndex) + { + Unit shaman = GetCaster(); + Aura unrelentingStorms = shaman.GetAura(SpellIds.UnrelentingStormsTalent); + if (unrelentingStorms == null) + return; + + long targetLimit = 0; + AuraEffect limitEffect = unrelentingStorms.GetEffect(0); + if (limitEffect != null) + targetLimit = limitEffect.GetAmount(); + + if (GetUnitTargetCountForEffect(effIndex) > targetLimit) + return; + + TimeSpan cooldown = TimeSpan.FromSeconds(0); + AuraEffect reductionPctEffect = unrelentingStorms.GetEffect(1); + if (reductionPctEffect != null) + { + SpellHistory.GetCooldownDurations(GetSpellInfo(), 0, ref cooldown); + + shaman.CastSpell(shaman, SpellIds.UnrelentingStormsReduction, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.BasePoint0, -(int)(MathFunctions.CalculatePct((int)cooldown.TotalMilliseconds, reductionPctEffect.GetAmount()))) } + }); + } + + if (shaman.HasAura(SpellIds.WindfuryAura)) + WindfuryProcEvent.Trigger(shaman, GetHitUnit()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(Trigger, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 470057 - Voltaic Blaze +class spell_sha_voltaic_blaze : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return spell_sha_maelstrom_weapon_base.Validate(); + } + + void ApplyFlameShock(uint effIndex) + { + Unit caster = GetCaster(); + var targets = new CastSpellTargetArg(GetHitUnit()); + caster.m_Events.AddEventAtOffset(() => + { + if (targets.Targets == null) + return; + + targets.Targets.Update(caster); + + caster.CastSpell(targets, SpellIds.FlameShock, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + }, TimeSpan.FromSeconds(500)); + } + + void EnergizeMaelstrom(uint effIndex) + { + spell_sha_maelstrom_weapon_base.GenerateMaelstromWeapon(GetCaster(), GetEffectValue()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(ApplyFlameShock, 0, SpellEffectName.SchoolDamage)); + OnEffectHitTarget.Add(new(EnergizeMaelstrom, 1, SpellEffectName.Dummy)); + } +} + +[Script] // 470058 - Voltaic Blaze +class spell_sha_voltaic_blaze_aura : AuraScript +{ + static bool CheckProc(ProcEventInfo eventInfo) + { + // 470057 - Voltaic Blaze does not have any unique SpellFamilyFlags, check by id + return eventInfo.GetSpellInfo().Id == SpellIds.VoltaicBlazeDamage; + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } +} + +[Script] // 470053 - Voltaic Blaze +class spell_sha_voltaic_blaze_talent : AuraScript +{ + static bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return RandomHelper.randChance(aurEff.GetAmount()); + } + + static void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + eventInfo.GetActor().CastSpell(eventInfo.GetActor(), SpellIds.VoltaicBlazeOverride); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 33757 - Windfury Weapon +class spell_sha_windfury_weapon : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.WindfuryEnchantment); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleEffect(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + + Item mainHand = GetCaster().ToPlayer().GetWeaponForAttack(WeaponAttackType.BaseAttack, false); + if (mainHand != null) + { + GetCaster().CastSpell(mainHand, SpellIds.WindfuryEnchantment, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask, + TriggeringSpell = GetSpell() + }); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleEffect, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 319773 - Windfury Weapon (proc) +class spell_sha_windfury_weapon_proc : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.WindfuryAttack, SpellIds.WindfuryVisual1, SpellIds.WindfuryVisual2, SpellIds.WindfuryVisual3, SpellIds.UnrulyWinds, SpellIds.ForcefulWindsTalent, SpellIds.ForcefulWindsProc); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + WindfuryProcEvent.Trigger(eventInfo.GetActor(), eventInfo.GetActionTarget()); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } +} + +// 462767 - Arctic Snowstorm +[Script] // 36797 - AreatriggerId +class areatrigger_sha_arctic_snowstorm(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (unit.GetAura(SpellIds.FrostShock, caster.GetGUID()) != null) + return; + + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, SpellIds.ArcticSnowstormSlow, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError }); + } + } + + public override void OnUnitExit(Unit unit) + { + unit.RemoveAurasDueToSpell(SpellIds.ArcticSnowstormSlow, at.GetCasterGUID()); + } +} + +// 192078 - Wind Rush Totem (Spell) +[Script] // 12676 - AreaTriggerId +class areatrigger_sha_wind_rush_totem(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + static int RefreshTime = 4500; + + int _refreshTimer = RefreshTime; + + public override void OnUpdate(uint diff) + { + _refreshTimer -= (int)diff; + if (_refreshTimer <= 0) { Unit caster = at.GetCaster(); if (caster != null) { - if (!caster.IsFriendlyTo(unit)) - return; - - caster.CastSpell(unit, SpellIds.WindRush, true); + foreach (ObjectGuid guid in at.GetInsideUnits()) + { + Unit unit = Global.ObjAccessor.GetUnit(caster, guid); + if (unit != null) + CastSpeedBuff(caster, unit); + } } + + _refreshTimer += RefreshTime; } } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + CastSpeedBuff(caster, unit); + } + + static void CastSpeedBuff(Unit caster, Unit unit) + { + if (!caster.IsValidAssistTarget(unit)) + return; + + caster.CastSpell(unit, SpellIds.WindRush, new CastSpellExtraArgs() { TriggerFlags = TriggerCastFlags.FullMask }); + } } \ No newline at end of file diff --git a/Source/Scripts/Spells/Warlock.cs b/Source/Scripts/Spells/Warlock.cs index 1b41672b4..7854506eb 100644 --- a/Source/Scripts/Spells/Warlock.cs +++ b/Source/Scripts/Spells/Warlock.cs @@ -1,1106 +1,1769 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; using Framework.Dynamic; +using Game.AI; using Game.Entities; using Game.Maps; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using static Global; -namespace Scripts.Spells.Warlock +namespace Scripts.Spells.Warlock; + +struct SpellIds { - struct SpellIds - { - public const uint AbsoluteCorruption = 196103; - public const uint CorruptionDamage = 146739; - public const uint CreateHealthstone = 23517; - public const uint DemonicCircleAllowCast = 62388; - public const uint DemonicCircleSummon = 48018; - public const uint DemonicCircleTeleport = 48020; - public const uint DevourMagicHeal = 19658; - public const uint DoomEnergize = 193318; - public const uint DrainSoulEnergize = 205292; - public const uint GlyphOfDemonTraining = 56249; - public const uint GlyphOfSoulSwap = 56226; - public const uint GlyphOfSuccubus = 56250; - public const uint ImmolatePeriodic = 157736; - public const uint ImprovedHealthFunnelBuffR1 = 60955; - public const uint ImprovedHealthFunnelBuffR2 = 60956; - public const uint ImprovedHealthFunnelR1 = 18703; - public const uint ImprovedHealthFunnelR2 = 18704; - public const uint RainOfFire = 5740; - public const uint RainOfFireDamage = 42223; - public const uint SeedOfCorruptionDamage = 27285; - public const uint SeedOfCorruptionGeneric = 32865; - public const uint ShadowBoltEnergize = 194192; - public const uint SoulshatterEffect = 32835; - public const uint SoulSwapCdMarker = 94229; - public const uint SoulSwapOverride = 86211; - public const uint SoulSwapModCost = 92794; - public const uint SoulSwapDotMarker = 92795; - public const uint UnstableAfflictionDamage = 196364; - public const uint UnstableAfflictionEnergize = 31117; - public const uint Shadowflame = 37378; - public const uint Flameshadow = 37379; - public const uint SummonSuccubus = 712; - public const uint SummonIncubus = 365349; - public const uint StrengthenPactSuccubus = 366323; - public const uint StrengthenPactIncubus = 366325; - public const uint SuccubusPact = 365360; - public const uint IncubusPact = 365355; + public const uint AbsoluteCorruption = 196103; + public const uint Agony = 980; + public const uint Backdraft = 196406; + public const uint BackdraftProc = 117828; + public const uint BilescourgeBombers = 267211; + public const uint BilescourgeBombersMissile = 267212; + public const uint BilescourgeBombersAreatrigger = 282248; + public const uint ChannelDemonfireActivator = 228312; + public const uint ChannelDemonfireDamage = 281362; + public const uint ChannelDemonfireSelector = 196449; + public const uint ConflagrateDebuff = 265931; + public const uint ConflagrateEnergize = 245330; + public const uint CorruptionDamage = 146739; + public const uint CreateHealthstone = 23517; + public const uint CurseOfExhaustion = 334275; + public const uint DeathsEmbrace = 453189; + public const uint DemonboltEnergize = 280127; + public const uint DemonicCircleAllowCast = 62388; + public const uint DemonicCircleSummon = 48018; + public const uint DemonicCircleTeleport = 48020; + public const uint DevourMagicHeal = 19658; + public const uint DoomEnergize = 193318; + public const uint DrainSoulEnergize = 205292; + public const uint Flameshadow = 37379; + public const uint GlyphOfDemonTraining = 56249; + public const uint GlyphOfSoulSwap = 56226; + public const uint GlyphOfSuccubus = 56250; + public const uint ImmolatePeriodic = 157736; + public const uint ImprovedHealthFunnelBuffR1 = 60955; + public const uint ImprovedHealthFunnelBuffR2 = 60956; + public const uint ImprovedHealthFunnelR1 = 18703; + public const uint ImprovedHealthFunnelR2 = 18704; + public const uint IncubusPact = 365355; + public const uint PerpetualUnstabilityDamage = 459461; + public const uint PerpetualUnstabilityTalent = 459376; + public const uint PyrogenicsDebuff = 387096; + public const uint PyrogenicsTalent = 387095; + public const uint RainOfFire = 5740; + public const uint RainOfFireDamage = 42223; + public const uint RoaringBlaze = 205184; + public const uint SeedOfCorruptionDamage = 27285; + public const uint SeedOfCorruptionGeneric = 32865; + public const uint ShadowburnEnergize = 245731; + public const uint ShadowBoltEnergize = 194192; + public const uint Shadowflame = 37378; + public const uint SiphonLifeHeal = 453000; + public const uint SoulFireEnergize = 281490; + public const uint SoulSwapCdMarker = 94229; + public const uint SoulSwapDotMarker = 92795; + public const uint SoulSwapModCost = 92794; + public const uint SoulSwapOverride = 86211; + public const uint SoulshatterEffect = 32835; + public const uint StrengthenPactIncubus = 366325; + public const uint StrengthenPactSuccubus = 366323; + public const uint SuccubusPact = 365360; + public const uint SummonIncubus = 365349; + public const uint SummonSuccubus = 712; + public const uint UnstableAfflictionDamage = 196364; + public const uint UnstableAfflictionEnergize = 31117; + public const uint VileTaintDamage = 386931; + public const uint VolatileAgonyDamage = 453035; + public const uint VolatileAgonyTalent = 453034; + public const uint WitherPeriodic = 445474; + public const uint WitherTalent = 445465; - public const uint GenReplenishment = 57669; - public const uint PriestShadowWordDeath = 32409; + public const uint GenReplenishment = 57669; + public const uint PriestShadowWordDeath = 32409; + + public const uint VisualWarlockBilescourgeBombersCrash = 75806; +} + +// 146739 - Corruption +[Script] // 445474 - Wither +class spell_warl_absolute_corruption : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.AbsoluteCorruption, 0)); } - // 146739 - Corruption - [Script] // 445474 - Wither - class spell_warl_absolute_corruption : SpellScript + public override bool Load() { - public override bool Validate(SpellInfo spellInfo) + return GetCaster().HasAura(SpellIds.AbsoluteCorruption); + } + + void HandleApply(uint effIndex) + { + Aura absoluteCorruption = GetCaster().GetAura(SpellIds.AbsoluteCorruption); + if (absoluteCorruption != null) { - return ValidateSpellEffect((SpellIds.AbsoluteCorruption, 0)); + TimeSpan duration = GetHitUnit().IsPvP() + ? TimeSpan.FromSeconds(absoluteCorruption.GetSpellInfo().GetEffect(0).CalcValue()) + : TimeSpan.FromSeconds(-1); + + GetHitAura().SetMaxDuration((int)duration.TotalMilliseconds); + GetHitAura().SetDuration((int)duration.TotalMilliseconds); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleApply, 0, SpellEffectName.ApplyAura)); + } +} + +[Script] // Called by 17962 - Conflagrate +class spell_warl_backdraft : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Backdraft, SpellIds.BackdraftProc); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.Backdraft); + } + + void HandleAfterCast() + { + Unit caster = GetCaster(); + caster.CastSpell(caster, SpellIds.BackdraftProc, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 710 - Banish +class spell_warl_banish : SpellScript +{ + void HandleBanish(SpellMissInfo missInfo) + { + if (missInfo != SpellMissInfo.Immune) + return; + + Unit target = GetHitUnit(); + if (target != null) + { + // Casting Banish on a banished target will remove applied aura + Aura banishAura = target.GetAura(GetSpellInfo().Id, GetCaster().GetGUID()); + if (banishAura != null) + banishAura.Remove(); + } + } + + public override void Register() + { + BeforeHit.Add(new(HandleBanish)); + } +} + +[Script] // 267211 - Bilescourge Bombers +class spell_warl_bilescourge_bombers : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.BilescourgeBombersAreatrigger); + } + + void HandleHit(uint effIndex) + { + GetCaster().CastSpell(GetCaster().GetPosition(), SpellIds.BilescourgeBombersAreatrigger, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleHit, 0, SpellEffectName.CreateAreaTrigger)); + } +} + +class BilescourgeBombersEvent(Unit caster, Position srcPos, Position destPos) : BasicEvent() +{ + public override bool Execute(ulong time, uint diff) + { + caster.SendPlayOrphanSpellVisual(srcPos, destPos, SpellIds.VisualWarlockBilescourgeBombersCrash, 0.5f, true); + caster.CastSpell(destPos, SpellIds.BilescourgeBombersMissile); + return true; + } +} + +[Script] // 15141 - Bilescourge Bombers +class at_warl_bilescourge_bombers(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) +{ + static byte MaxTicks = 12; + + public override void OnCreate(Spell creatingSpell) + { + Unit caster = at.GetCaster(); + if (caster == null) + return; + + AreaTrigger targetAt = caster.GetAreaTrigger(SpellIds.BilescourgeBombers); + if (targetAt == null) + return; + + int tickRate = at.GetTotalDuration() / MaxTicks; + + for (byte i = 1; i <= 12; i++) + caster.m_Events.AddEventAtOffset(new BilescourgeBombersEvent(caster, at.GetPosition(), targetAt.GetPosition()), TimeSpan.FromSeconds(tickRate * i)); + } +} + +[Script] // 111400 - Burning Rush +class spell_warl_burning_rush : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1)); + } + + SpellCastResult CheckApplyAura() + { + Unit caster = GetCaster(); + + if (caster.GetHealthPct() <= (float)GetEffectInfo(1).CalcValue(caster)) + { + SetCustomCastResultMessage(SpellCustomErrors.YouDontHaveEnoughHealth); + return SpellCastResult.CustomError; } - public override bool Load() - { - return GetCaster().HasAura(SpellIds.AbsoluteCorruption); - } + return SpellCastResult.SpellCastOk; + } - void HandleApply(uint effIndex) + public override void Register() + { + OnCheckCast.Add(new(CheckApplyAura)); + } +} + +[Script] // 111400 - Burning Rush +class spell_warl_burning_rush_aura : AuraScript +{ + void PeriodicTick(AuraEffect aurEff) + { + if (GetTarget().GetHealthPct() <= (float)aurEff.GetAmount()) { - Aura absoluteCorruption = GetCaster().GetAura(SpellIds.AbsoluteCorruption); - if (absoluteCorruption != null) + PreventDefaultAction(); + Remove(); + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new(PeriodicTick, 1, AuraType.PeriodicDamagePercent)); + } +} + +[Script] // 152108 - Cataclysm +class spell_warl_cataclysm : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImmolatePeriodic); + } + + void HandleHit(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ImmolatePeriodic, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 228312 - Immolate (attached to 157736 - Immolate and 445474 - Wither) +class spell_warl_channel_demonfire_activator : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChannelDemonfireActivator); + } + + void ApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.ChannelDemonfireActivator, new CastSpellExtraArgs() { - TimeSpan duration = GetHitUnit().IsPvP() - ? TimeSpan.FromSeconds(absoluteCorruption.GetSpellInfo().GetEffect(0).CalcValue()) - : TimeSpan.FromMilliseconds(-1); - - GetHitAura().SetMaxDuration((int)duration.TotalMilliseconds); - GetHitAura().SetDuration((int)duration.TotalMilliseconds); - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleApply, 0, SpellEffectName.ApplyAura)); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + SpellValueOverrides = { new(SpellValueMod.Duration, GetDuration()) } + }); } - [Script] // 710 - Banish - class spell_warl_banish : SpellScript + void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) { - void HandleBanish(SpellMissInfo missInfo) - { - if (missInfo != SpellMissInfo.Immune) - return; + Unit caster = GetCaster(); + if (caster == null) + return; - Unit target = GetHitUnit(); - if (target != null) + UnitAuraCheck check = new(true, GetId(), caster.GetGUID()); + UnitSearcher searcher = new(caster, check); + Cell.VisitAllObjects(caster, searcher, 100.0f); + + if (searcher.GetResult() == null) + caster.RemoveAurasDueToSpell(SpellIds.ChannelDemonfireActivator); + } + + public override void Register() + { + OnEffectApply.Add(new(ApplyEffect, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.RealOrReapplyMask)); + OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); + } +} + +[Script] // 196447 - Channel Demonfire +class spell_warl_channel_demonfire_periodic : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChannelDemonfireSelector); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + { + caster.CastSpell(caster, SpellIds.ChannelDemonfireSelector, new CastSpellExtraArgs() { - // Casting Banish on a banished target will Remove applied aura - Aura banishAura = target.GetAura(GetSpellInfo().Id, GetCaster().GetGUID()); - if (banishAura != null) - banishAura.Remove(); - } - } - - public override void Register() - { - BeforeHit.Add(new(HandleBanish)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); } } - [Script] // 111400 - Burning Rush - class spell_warl_burning_rush : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDummy)); + } +} + +[Script] // 196449 - Channel Demonfire +class spell_warl_channel_demonfire_selector : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ChannelDemonfireDamage, SpellIds.ImmolatePeriodic, SpellIds.WitherTalent, SpellIds.ImmolatePeriodic); + } + + void FilterTargets(List targets) + { + uint auraFilter = GetCaster().HasAura(SpellIds.WitherTalent) + ? SpellIds.WitherPeriodic + : SpellIds.ImmolatePeriodic; + targets.RemoveAll(new UnitAuraCheck(false, auraFilter, GetCaster().GetGUID())); + } + + void HandleDamage(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ChannelDemonfireDamage, new CastSpellExtraArgs() { - return ValidateSpellEffect((spellInfo.Id, 1)); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); + OnEffectLaunchTarget.Add(new(HandleDamage, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 116858 - Chaos Bolt +class spell_warl_chaos_bolt : SpellScript +{ + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleDummy(uint effIndex) + { + SetHitDamage(GetHitDamage() + MathFunctions.CalculatePct(GetHitDamage(), GetCaster().ToPlayer().m_activePlayerData.SpellCritPercentage)); + } + + void CalcCritChance(Unit victim, ref float critChance) + { + critChance = 100.0f; + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.SchoolDamage)); + OnCalcCritChance.Add(new(CalcCritChance)); + } +} + +[Script] // 77220 - Mastery: Chaotic Energies +class spell_warl_chaotic_energies : AuraScript +{ + void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) + { + AuraEffect aura = GetEffect(1); + if (aura == null || !GetTargetApplication().HasEffect(1)) + { + PreventDefaultAction(); + return; } - SpellCastResult CheckApplyAura() - { - Unit caster = GetCaster(); + // You take ${$s2/3}% reduced damage + float damageReductionPct = (float)(aura.GetAmount()) / 3; + // plus a random amount of up to ${$s2/3}% additional reduced damage + damageReductionPct += RandomHelper.FRand(0.0f, damageReductionPct); - if (caster.GetHealthPct() <= (float)(GetEffectInfo(1).CalcValue(caster))) + absorbAmount = MathFunctions.CalculatePct(dmgInfo.GetDamage(), damageReductionPct); + } + + public override void Register() + { + OnEffectAbsorb.Add(new(HandleAbsorb, 2)); + } +} + +[Script] // 17962 - Conflagrate +class spell_warl_conflagrate : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ConflagrateEnergize); + } + + void HandleAfterCast(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.ConflagrateEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleAfterCast, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 6201 - Create Healthstone +class spell_warl_create_healthstone : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CreateHealthstone); + } + + public override bool Load() + { + return GetCaster().IsPlayer(); + } + + void HandleScriptEffect(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.CreateHealthstone, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); + } +} + +[Script] // 108416 - Dark Pact +class spell_warl_dark_pact : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((spellInfo.Id, 1), (spellInfo.Id, 2)); + } + + void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + canBeRecalculated = false; + Unit caster = GetCaster(); + if (caster != null) + { + float extraAmount = caster.SpellBaseDamageBonusDone(GetSpellInfo().GetSchoolMask()) * 2.5f; + ulong absorb = caster.CountPctFromCurHealth(GetEffectInfo(1).CalcValue(caster)); + caster.SetHealth((ulong)(caster.GetHealth() - absorb)); + amount = (int)(MathFunctions.CalculatePct(absorb, GetEffectInfo(2).CalcValue(caster)) + extraAmount); + } + } + + public override void Register() + { + DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); + } +} + +class spell_warl_deaths_embrace_impl +{ + public static void HandleDamageOrHealingCalculation(Unit caster, Unit target, ref float pctMod, uint inreaseEffect, uint healthLimitEffect) + { + Aura deathsEmbrace = caster.GetAura(SpellIds.DeathsEmbrace, ObjectGuid.Empty, ObjectGuid.Empty, 1u << (int)inreaseEffect | 1u << (int)healthLimitEffect); + if (deathsEmbrace == null) + return; + + if (!target.HealthBelowPct(deathsEmbrace.GetEffect(healthLimitEffect).GetAmount())) + return; + + MathFunctions.AddPct(ref pctMod, deathsEmbrace.GetEffect(inreaseEffect).GetAmount()); + } +} + +[Script] // Called by 324540 - Malefic Rapture +class spell_warl_deaths_embrace : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DeathsEmbrace, 3)); + } + + void HandleDamageCalculation(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + spell_warl_deaths_embrace_impl.HandleDamageOrHealingCalculation(GetCaster(), victim, ref pctMod, 2, 3); + } + + public override void Register() + { + CalcDamage.Add(new(HandleDamageCalculation)); + } +} + +[Script] // Called by 980 - Agony, 146739 - Corruption and 316099 - Unstable Affliction +class spell_warl_deaths_embrace_dots : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DeathsEmbrace, 3)); + } + + void CalculateDamage(AuraEffect aurEff, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + Unit caster = GetCaster(); + if (caster != null) + spell_warl_deaths_embrace_impl.HandleDamageOrHealingCalculation(caster, victim, ref pctMod, 2, 3); + } + + public override void Register() + { + DoEffectCalcDamageAndHealing.Add(new(CalculateDamage, SpellConst.EffectAll, AuraType.PeriodicDamage)); + } +} + +[Script] // 234153 - Drain Life +class spell_warl_deaths_embrace_drain_life : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DeathsEmbrace, 1)); + } + + void CalculateHeal(AuraEffect aurEff, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + if (caster != victim) // check who is being targeted, this hook is called for both damage and healing of PeriodicLeech + return; + + spell_warl_deaths_embrace_impl.HandleDamageOrHealingCalculation(caster, caster, ref pctMod, 0, 1); + } + + public override void Register() + { + DoEffectCalcDamageAndHealing.Add(new(CalculateHeal, 0, AuraType.PeriodicLeech)); + } +} + +[Script] // 264178 - Demonbolt +class spell_warl_demonbolt : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DemonboltEnergize); + } + + void HandleAfterCast() + { + GetCaster().CastSpell(GetCaster(), SpellIds.DemonboltEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(HandleAfterCast)); + } +} + +[Script] // 48018 - Demonic Circle: Summon +class spell_warl_demonic_circle_summon : AuraScript +{ + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + // If effect is removed by expire remove the summoned demonic circle too. + if (!mode.HasAnyFlag(AuraEffectHandleModes.Reapply)) + GetTarget().RemoveGameObject(GetId(), true); + + GetTarget().RemoveAura(SpellIds.DemonicCircleAllowCast); + } + + void HandleDummyTick(AuraEffect aurEff) + { + GameObject circle = GetTarget().GetGameObject(GetId()); + if (circle != null) + { + // Here we check if player is in demonic circle teleport range, if so add + // WarlockDemonicCircleAllowCast; allowing him to cast the WarlockDemonicCircleTeleport. + // If not in range remove the WarlockDemonicCircleAllowCast. + + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.DemonicCircleTeleport, GetCastDifficulty()); + + if (GetTarget().IsWithinDist(circle, spellInfo.GetMaxRange(true))) { - SetCustomCastResultMessage(SpellCustomErrors.YouDontHaveEnoughHealth); - return SpellCastResult.CustomError; - } - - return SpellCastResult.SpellCastOk; - } - - public override void Register() - { - OnCheckCast.Add(new(CheckApplyAura)); - } - } - - [Script] // 111400 - Burning Rush - class spell_warl_burning_rush_AuraScript : AuraScript - { - void PeriodicTick(AuraEffect aurEff) - { - if (GetTarget().GetHealthPct() <= (float)(aurEff.GetAmount())) - { - PreventDefaultAction(); - Remove(); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(PeriodicTick, 1, AuraType.PeriodicDamagePercent)); - } - } - - [Script] // 116858 - Chaos Bolt - class spell_warl_chaos_bolt : SpellScript - { - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleDummy(uint effIndex) - { - SetHitDamage(GetHitDamage() + MathFunctions.CalculatePct(GetHitDamage(), GetCaster().ToPlayer().m_activePlayerData.SpellCritPercentage)); - } - - void CalcCritChance(Unit victim, ref float critChance) - { - critChance = 100.0f; - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.SchoolDamage)); - OnCalcCritChance.Add(new(CalcCritChance)); - } - } - - [Script] // 77220 - Mastery: Chaotic Energies - class spell_warl_chaotic_energies : AuraScript - { - void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount) - { - AuraEffect effect1 = GetEffect(1); - if (effect1 == null || !GetTargetApplication().HasEffect(1)) - { - PreventDefaultAction(); - return; - } - - // You take ${$s2/3}% reduced damage - float damageReductionPct = (float)(effect1.GetAmount()) / 3; - // plus a random amount of up to ${$s2/3}% additional reduced damage - damageReductionPct += RandomHelper.FRand(0.0f, damageReductionPct); - - absorbAmount = MathFunctions.CalculatePct(dmgInfo.GetDamage(), damageReductionPct); - } - - public override void Register() - { - OnEffectAbsorb.Add(new(HandleAbsorb, 2)); - } - } - - [Script] // 6201 - Create Healthstone - class spell_warl_create_healthstone : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CreateHealthstone); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); - } - - void HandleScriptEffect(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), SpellIds.CreateHealthstone, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect)); - } - } - - [Script] // 108416 - Dark Pact - class spell_warl_dark_pact : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellEffect((spellInfo.Id, 1), (spellInfo.Id, 2)); - } - - void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - canBeRecalculated = false; - Unit caster = GetCaster(); - if (caster != null) - { - float extraAmount = caster.SpellBaseDamageBonusDone(GetSpellInfo().GetSchoolMask()) * 2.5f; - ulong absorb = caster.CountPctFromCurHealth(GetEffectInfo(1).CalcValue(caster)); - caster.SetHealth(caster.GetHealth() - absorb); - amount = (int)(MathFunctions.CalculatePct(absorb, GetEffectInfo(2).CalcValue(caster)) + extraAmount); - } - } - - public override void Register() - { - DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb)); - } - } - - [Script] // 48018 - Demonic Circle: Summon - class spell_warl_demonic_circle_summon : AuraScript - { - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // If effect is Removed by expire Remove the summoned demonic circle too. - if (!mode.HasFlag(AuraEffectHandleModes.Reapply)) - GetTarget().RemoveGameObject(GetId(), true); - - GetTarget().RemoveAura(SpellIds.DemonicCircleAllowCast); - } - - void HandleDummyTick(AuraEffect aurEff) - { - GameObject circle = GetTarget().GetGameObject(GetId()); - if (circle != null) - { - // Here we check if player is in demonic circle teleport range, if so add - // WarlockDemonicCircleAllowCast; allowing him to cast the WarlockDemonicCircleTeleport. - // If not in range Remove the WarlockDemonicCircleAllowCast. - - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.DemonicCircleTeleport, GetCastDifficulty()); - - if (GetTarget().IsWithinDist(circle, spellInfo.GetMaxRange(true))) - { - if (!GetTarget().HasAura(SpellIds.DemonicCircleAllowCast)) - GetTarget().CastSpell(GetTarget(), SpellIds.DemonicCircleAllowCast, true); - } - else - GetTarget().RemoveAura(SpellIds.DemonicCircleAllowCast); - } - } - - public override void Register() - { - OnEffectRemove.Add(new(HandleRemove, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); - OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy)); - } - } - - [Script] // 48020 - Demonic Circle: Teleport - class spell_warl_demonic_circle_teleport : AuraScript - { - void HandleTeleport(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Player player = GetTarget().ToPlayer(); - if (player != null) - { - GameObject circle = player.GetGameObject(SpellIds.DemonicCircleSummon); - if (circle != null) - { - player.NearTeleportTo(circle.GetPositionX(), circle.GetPositionY(), circle.GetPositionZ(), circle.GetOrientation()); - player.RemoveMovementImpairingAuras(false); - } - } - } - - public override void Register() - { - OnEffectApply.Add(new(HandleTeleport, 0, AuraType.MechanicImmunity, AuraEffectHandleModes.Real)); - } - } - - [Script] // 67518, 19505 - Devour Magic - class spell_warl_devour_magic : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlyphOfDemonTraining, SpellIds.DevourMagicHeal) - && ValidateSpellEffect((spellInfo.Id, 1)); - } - - void OnSuccessfulDispel(uint effIndex) - { - Unit caster = GetCaster(); - CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); - args.AddSpellMod(SpellValueMod.BasePoint0, GetEffectInfo(1).CalcValue(caster)); - - caster.CastSpell(caster, SpellIds.DevourMagicHeal, args); - - // Glyph of Felhunter - Unit owner = caster.GetOwner(); - if (owner?.GetAura(SpellIds.GlyphOfDemonTraining) != null) - owner.CastSpell(owner, SpellIds.DevourMagicHeal, args); - } - - public override void Register() - { - OnEffectSuccessfulDispel.Add(new(OnSuccessfulDispel, 0, SpellEffectName.Dispel)); - } - } - - [Script] // 603 - Doom - class spell_warl_doom : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DoomEnergize); - } - - void HandleEffectPeriodic(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, SpellIds.DoomEnergize, true); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDamage)); - } - } - - [Script] // 198590 - Drain Soul - class spell_warl_drain_soul : AuraScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.DrainSoulEnergize); - } - - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) - return; - - Unit caster = GetCaster(); - if (caster != null) - caster.CastSpell(caster, SpellIds.DrainSoulEnergize, true); - } - - public override void Register() - { - AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); - } - } - - [Script] // 48181 - Haunt - class spell_warl_haunt : AuraScript - { - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) - { - if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Death) - { - Unit caster = GetCaster(); - if (caster != null) - caster.GetSpellHistory().ResetCooldown(GetId(), true); - } - } - - public override void Register() - { - OnEffectRemove.Add(new(HandleRemove, 1, AuraType.ModSchoolMaskDamageFromCaster, AuraEffectHandleModes.Real)); - } - } - - [Script] // 755 - Health Funnel - class spell_warl_health_funnel : AuraScript - { - void ApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - Unit target = GetTarget(); - if (caster.HasAura(SpellIds.ImprovedHealthFunnelR2)) - target.CastSpell(target, SpellIds.ImprovedHealthFunnelBuffR2, true); - else if (caster.HasAura(SpellIds.ImprovedHealthFunnelR1)) - target.CastSpell(target, SpellIds.ImprovedHealthFunnelBuffR1, true); - } - - void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) - { - Unit target = GetTarget(); - target.RemoveAurasDueToSpell(SpellIds.ImprovedHealthFunnelBuffR1); - target.RemoveAurasDueToSpell(SpellIds.ImprovedHealthFunnelBuffR2); - } - - void OnPeriodic(AuraEffect aurEff) - { - Unit caster = GetCaster(); - if (caster == null) - return; - //! Hack for self damage, is not blizz :/ - uint damage = (uint)caster.CountPctFromMaxHealth(aurEff.GetBaseAmount()); - - Player modOwner = caster.GetSpellModOwner(); - if (modOwner != null) - modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.PowerCost0, ref damage); - - SpellNonMeleeDamage damageInfo = new(caster, caster, GetSpellInfo(), GetAura().GetSpellVisual(), GetSpellInfo().SchoolMask, GetAura().GetCastId()); - damageInfo.periodicLog = true; - damageInfo.damage = damage; - caster.DealSpellDamage(damageInfo, false); - caster.SendSpellNonMeleeDamageLog(damageInfo); - } - - public override void Register() - { - OnEffectApply.Add(new(ApplyEffect, 0, AuraType.ObsModHealth, AuraEffectHandleModes.Real)); - OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.ObsModHealth, AuraEffectHandleModes.Real)); - OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.ObsModHealth)); - } - } - - [Script] // 6262 - Healthstone - class spell_warl_healthstone_heal : SpellScript - { - void HandleOnHit() - { - int heal = (int)MathFunctions.CalculatePct(GetCaster().GetCreateHealth(), GetHitHeal()); - SetHitHeal(heal); - } - - public override void Register() - { - OnHit.Add(new(HandleOnHit)); - } - } - - [Script] // 348 - Immolate - class spell_warl_immolate : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ImmolatePeriodic); - } - - void HandleOnEffectHit(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.ImmolatePeriodic, GetSpell()); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleOnEffectHit, 0, SpellEffectName.SchoolDamage)); - } - } - - [Script] // 366330 - Random Sayaad - class spell_warl_random_sayaad : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SuccubusPact, SpellIds.IncubusPact); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - - caster.RemoveAurasDueToSpell(SpellIds.SuccubusPact); - caster.RemoveAurasDueToSpell(SpellIds.IncubusPact); - - Player player = GetCaster().ToPlayer(); - if (player == null) - return; - - Pet pet = player.GetPet(); - if (pet != null) - { - if (pet.IsPetSayaad()) - pet.DespawnOrUnsummon(); - } - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } - } - - // 366323 - Strengthen Pact - Succubus - // 366325 - Strengthen Pact - Incubus - [Script] // 366222 - Summon Sayaad - class spell_warl_sayaad_precast_disorientation : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SharedConst.SpellPetSummoningDisorientation); - } - - // Note: this is a special case in which the warlock's minion pet must also cast Summon Disorientation at the beginning Math.Since this is only handled by SpellEffectSummonPet in Spell.CheckCast. - public override void OnPrecast() - { - Player player = GetCaster().ToPlayer(); - if (player == null) - return; - - Pet pet = player.GetPet(); - if (pet != null) - pet.CastSpell(pet, SharedConst.SpellPetSummoningDisorientation, new CastSpellExtraArgs(TriggerCastFlags.FullMask) - .SetOriginalCaster(pet.GetGUID()) - .SetTriggeringSpell(GetSpell())); - } - - public override void Register() { } - } - - [Script] // 6358 - Seduction (Special Ability) - class spell_warl_seduction : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlyphOfSuccubus, SpellIds.PriestShadowWordDeath); - } - - void HandleScriptEffect(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - if (target != null) - { - if (caster.GetOwner() != null && caster.GetOwner().HasAura(SpellIds.GlyphOfSuccubus)) - { - target.RemoveAurasByType(AuraType.PeriodicDamage, ObjectGuid.Empty, target.GetAura(SpellIds.PriestShadowWordDeath)); // Sw:D shall not be Removed. - target.RemoveAurasByType(AuraType.PeriodicDamagePercent); - target.RemoveAurasByType(AuraType.PeriodicLeech); - } - } - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ApplyAura)); - } - } - - [Script] // 27285 - Seed of Corruption (damage) - class spell_warl_seed_of_corruption : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.CorruptionDamage); - } - - void HandleHit(uint effIndex) - { - GetCaster().CastSpell(GetHitUnit(), SpellIds.CorruptionDamage, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); - } - } - - [Script] - class spell_warl_seed_of_corruption_dummy : SpellScript - { - void RemoveVisualMissile(ref WorldObject target) - { - target = null; - } - - void SelectTarget(List targets) - { - if (targets.Count < 2) - return; - - if (!GetExplTargetUnit().HasAura(GetSpellInfo().Id, GetCaster().GetGUID())) - { - // primary target doesn't have seed, keep it - targets.Clear(); - targets.Add(GetExplTargetUnit()); + if (!GetTarget().HasAura(SpellIds.DemonicCircleAllowCast)) + GetTarget().CastSpell(GetTarget(), SpellIds.DemonicCircleAllowCast, true); } else - { - // primary target has seed, select random other target with no seed - targets.RemoveAll(new UnitAuraCheck(true, GetSpellInfo().Id, GetCaster().GetGUID())); - if (!targets.Empty()) - targets.RandomResize(1); - else - targets.Add(GetExplTargetUnit()); - } - } - - public override void Register() - { - OnObjectTargetSelect.Add(new(RemoveVisualMissile, 0, Targets.UnitTargetEnemy)); - OnObjectAreaTargetSelect.Add(new(SelectTarget, 1, Targets.UnitDestAreaEnemy)); - OnObjectAreaTargetSelect.Add(new(SelectTarget, 2, Targets.UnitDestAreaEnemy)); + GetTarget().RemoveAura(SpellIds.DemonicCircleAllowCast); } } - [Script] // 27243 - Seed of Corruption - class spell_warl_seed_of_corruption_dummy_aura : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SeedOfCorruptionDamage); - } + OnEffectRemove.Add(new(HandleRemove, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.RealOrReapplyMask)); + OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy)); + } +} - void OnPeriodic(AuraEffect aurEff) +[Script] // 48020 - Demonic Circle: Teleport +class spell_warl_demonic_circle_teleport : AuraScript +{ + void HandleTeleport(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Player player = GetTarget().ToPlayer(); + if (player != null) + { + GameObject circle = player.GetGameObject(SpellIds.DemonicCircleSummon); + if (circle != null) + { + player.NearTeleportTo(circle.GetPositionX(), circle.GetPositionY(), circle.GetPositionZ(), circle.GetOrientation()); + player.RemoveMovementImpairingAuras(false); + } + } + } + + public override void Register() + { + OnEffectApply.Add(new(HandleTeleport, 0, AuraType.MechanicImmunity, AuraEffectHandleModes.Real)); + } +} + +[Script] // 67518, 19505 - Devour Magic +class spell_warl_devour_magic : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlyphOfDemonTraining, SpellIds.DevourMagicHeal) + && ValidateSpellEffect((spellInfo.Id, 1)); + } + + void OnSuccessfulDispel(uint effIndex) + { + Unit caster = GetCaster(); + CastSpellExtraArgs args = new(); + args.TriggerFlags = TriggerCastFlags.FullMask; + args.AddSpellMod(SpellValueMod.BasePoint0, GetEffectInfo(1).CalcValue(caster)); + + caster.CastSpell(caster, SpellIds.DevourMagicHeal, args); + + // Glyph of Felhunter + Unit owner = caster.GetOwner(); + if (owner != null) + if (owner.GetAura(SpellIds.GlyphOfDemonTraining) != null) + owner.CastSpell(owner, SpellIds.DevourMagicHeal, args); + } + + public override void Register() + { + OnEffectSuccessfulDispel.Add(new(OnSuccessfulDispel, 0, SpellEffectName.Dispel)); + } +} + +[Script] // 603 - Doom +class spell_warl_doom : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DoomEnergize); + } + + void HandleEffectPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.DoomEnergize, true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(HandleEffectPeriodic, 0, AuraType.PeriodicDamage)); + } +} + +[Script] // 198590 - Drain Soul +class spell_warl_drain_soul : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DrainSoulEnergize) + && ValidateSpellEffect((spellInfo.Id, 2)); + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) + return; + + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(caster, SpellIds.DrainSoulEnergize, true); + } + + void CalculateDamage(AuraEffect aurEff, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + if (victim.HealthBelowPct(GetEffectInfo(2).CalcValue(GetCaster()))) + MathFunctions.AddPct(ref pctMod, GetEffectInfo(1).CalcValue(GetCaster())); + } + + public override void Register() + { + AfterEffectRemove.Add(new(HandleRemove, 0, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); + DoEffectCalcDamageAndHealing.Add(new(CalculateDamage, 0, AuraType.PeriodicDamage)); + } +} + +[Script] // 48181 - Haunt +class spell_warl_haunt : AuraScript +{ + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Death) { Unit caster = GetCaster(); if (caster != null) - caster.CastSpell(GetTarget(), SpellIds.SeedOfCorruptionDamage, aurEff); - } - - void CalculateBuffer(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) - { - Unit caster = GetCaster(); - if (caster == null) - return; - - amount = caster.SpellBaseDamageBonusDone(GetSpellInfo().GetSchoolMask()) * GetEffectInfo(0).CalcValue(caster) / 100; - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null) - return; - - Unit caster = GetCaster(); - if (caster == null) - return; - - if (damageInfo.GetAttacker() == null || damageInfo.GetAttacker() != caster) - return; - - // other seed explosions detonate this instantly, no matter what damage amount is - if (damageInfo.GetSpellInfo() == null || damageInfo.GetSpellInfo().Id != SpellIds.SeedOfCorruptionDamage) - { - int amount = (int)(aurEff.GetAmount() - damageInfo.GetDamage()); - if (amount > 0) - { - aurEff.SetAmount(amount); - if (!GetTarget().HealthBelowPctDamaged(1, damageInfo.GetDamage())) - return; - } - } - - Remove(); - - caster.CastSpell(eventInfo.GetActionTarget(), SpellIds.SeedOfCorruptionDamage, aurEff); - } - - public override void Register() - { - OnEffectPeriodic.Add(new(OnPeriodic, 1, AuraType.PeriodicDamage)); - DoEffectCalcAmount.Add(new(CalculateBuffer, 2, AuraType.Dummy)); - OnEffectProc.Add(new(HandleProc, 2, AuraType.Dummy)); + caster.GetSpellHistory().ResetCooldown(GetId(), true); } } - // 32863 - Seed of Corruption - // 36123 - Seed of Corruption - // 38252 - Seed of Corruption - // 39367 - Seed of Corruption - // 44141 - Seed of Corruption - // 70388 - Seed of Corruption - [Script] // Monster spells, triggered only on amount drop (not on death) - class spell_warl_seed_of_corruption_generic : AuraScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) + OnEffectRemove.Add(new(HandleRemove, 1, AuraType.ModSchoolMaskDamageFromCaster, AuraEffectHandleModes.Real)); + } +} + +[Script] // 755 - Health Funnel +class spell_warl_health_funnel : AuraScript +{ + void ApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + Unit target = GetTarget(); + if (caster.HasAura(SpellIds.ImprovedHealthFunnelR2)) + target.CastSpell(target, SpellIds.ImprovedHealthFunnelBuffR2, true); + else if (caster.HasAura(SpellIds.ImprovedHealthFunnelR1)) + target.CastSpell(target, SpellIds.ImprovedHealthFunnelBuffR1, true); + } + + void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) + { + Unit target = GetTarget(); + target.RemoveAurasDueToSpell(SpellIds.ImprovedHealthFunnelBuffR1); + target.RemoveAurasDueToSpell(SpellIds.ImprovedHealthFunnelBuffR2); + } + + void OnPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster == null) + return; + //! Hack for self damage, is not blizz :/ + uint damage = (uint)caster.CountPctFromMaxHealth(aurEff.GetBaseAmount()); + + Player modOwner = caster.GetSpellModOwner(); + if (modOwner != null) + modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.PowerCost0, ref damage); + + SpellNonMeleeDamage damageInfo = new(caster, caster, GetSpellInfo(), GetAura().GetSpellVisual(), GetSpellInfo().SchoolMask, GetAura().GetCastId()); + damageInfo.periodicLog = true; + damageInfo.damage = damage; + caster.DealSpellDamage(damageInfo, false); + caster.SendSpellNonMeleeDamageLog(damageInfo); + } + + public override void Register() + { + OnEffectApply.Add(new(ApplyEffect, 0, AuraType.ObsModHealth, AuraEffectHandleModes.Real)); + OnEffectRemove.Add(new(RemoveEffect, 0, AuraType.ObsModHealth, AuraEffectHandleModes.Real)); + OnEffectPeriodic.Add(new(OnPeriodic, 0, AuraType.ObsModHealth)); + } +} + +[Script] // 6262 - Healthstone +class spell_warl_healthstone_heal : SpellScript +{ + void HandleOnHit() + { + int heal = (int)MathFunctions.CalculatePct(GetCaster().GetCreateHealth(), GetHitHeal()); + SetHitHeal(heal); + } + + public override void Register() + { + OnHit.Add(new(HandleOnHit)); + } +} + +[Script] // 348 - Immolate +class spell_warl_immolate : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImmolatePeriodic); + } + + void HandleOnEffectHit(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ImmolatePeriodic, GetSpell()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleOnEffectHit, 0, SpellEffectName.SchoolDamage)); + } +} + +// Called by 316099 - Unstable Affliction +[Script] // 459376 - Perpetual Unstability +class spell_warl_perpetual_unstability : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PerpetualUnstabilityTalent, SpellIds.PerpetualUnstabilityDamage); + } + + void TriggerExplosion() + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + AuraEffect perpetualUnstability = caster.GetAuraEffect(SpellIds.PerpetualUnstabilityTalent, 0); + if (perpetualUnstability != null) { - return ValidateSpellInfo(SpellIds.SeedOfCorruptionGeneric); + Aura unstableAfflictionAura = target.GetAura(GetSpellInfo().Id, caster.GetGUID()); + if (unstableAfflictionAura != null) + { + TimeSpan maxUnstableAfflictionDuration = TimeSpan.FromSeconds(perpetualUnstability.GetAmount()); + if (TimeSpan.FromSeconds(unstableAfflictionAura.GetDuration()) <= maxUnstableAfflictionDuration) + caster.CastSpell(target, SpellIds.PerpetualUnstabilityDamage, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); + } + } + } + + public override void Register() + { + OnHit.Add(new(TriggerExplosion)); + } +} + +[Script] // 387095 - Pyrogenics +class spell_warl_pyrogenics : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PyrogenicsDebuff); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo procInfo) + { + GetTarget().CastSpell(procInfo.GetActionTarget(), SpellIds.PyrogenicsDebuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringAura = aurEff + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.AddFlatModifierBySpellLabel)); + } +} + +// 5740 - Rain of Fire +[Script] /// Updated 11.0.2 +class spell_warl_rain_of_fire : AuraScript +{ + void HandleDummyTick(AuraEffect aurEff) + { + List rainOfFireAreaTriggers = GetTarget().GetAreaTriggers(SpellIds.RainOfFire); + List targetsInRainOfFire = new(); + + foreach (AreaTrigger rainOfFireAreaTrigger in rainOfFireAreaTriggers) + { + var insideTargets = rainOfFireAreaTrigger.GetInsideUnits(); + targetsInRainOfFire.AddRange(insideTargets); } - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + foreach (ObjectGuid insideTargetGuid in targetsInRainOfFire) { - PreventDefaultAction(); - DamageInfo damageInfo = eventInfo.GetDamageInfo(); - if (damageInfo == null || damageInfo.GetDamage() == 0) - return; + Unit insideTarget = Global.ObjAccessor.GetUnit(GetTarget(), insideTargetGuid); + if (insideTarget != null) + if (!GetTarget().IsFriendlyTo(insideTarget)) + GetTarget().CastSpell(insideTarget, SpellIds.RainOfFireDamage, true); + } + } + public override void Register() + { + OnEffectPeriodic.Add(new(HandleDummyTick, 2, AuraType.PeriodicDummy)); + } +} + +[Script] // 366330 - Random Sayaad +class spell_warl_random_sayaad : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SuccubusPact, SpellIds.IncubusPact); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + + caster.RemoveAurasDueToSpell(SpellIds.SuccubusPact); + caster.RemoveAurasDueToSpell(SpellIds.IncubusPact); + + Player player = GetCaster().ToPlayer(); + if (player == null) + return; + + Pet pet = player.GetPet(); + if (pet != null) + { + if (pet.IsPetSayaad()) + pet.DespawnOrUnsummon(); + } + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // Called by 17962 - Conflagrate +class spell_warl_roaring_blaze : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.RoaringBlaze, SpellIds.ConflagrateDebuff); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.RoaringBlaze); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.ConflagrateDebuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.SchoolDamage)); + } +} + +// 366323 - Strengthen Pact - Succubus +// 366325 - Strengthen Pact - Incubus +[Script] // 366222 - Summon Sayaad +class spell_warl_sayaad_precast_disorientation : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SharedConst.SpellPetSummoningDisorientation); + } + + // Note: this is a special case in which the warlock's minion pet must also cast Summon Disorientation at the beginning since this is only handled by SpellEffectSummonPet in Spell::CheckCast. + public override void OnPrecast() + { + Player player = GetCaster().ToPlayer(); + if (player == null) + return; + + Pet pet = player.GetPet(); + if (pet != null) + { + pet.CastSpell(pet, SharedConst.SpellPetSummoningDisorientation, new CastSpellExtraArgs(TriggerCastFlags.FullMask) + .SetOriginalCaster(pet.GetGUID()) + .SetTriggeringSpell(GetSpell())); + } + } + + public override void Register() + { + } +} + +[Script] // 6358 - Seduction (Special Ability) +class spell_warl_seduction : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlyphOfSuccubus, SpellIds.PriestShadowWordDeath); + } + + void HandleScriptEffect(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target != null) + { + if (caster.GetOwner() != null && caster.GetOwner().HasAura(SpellIds.GlyphOfSuccubus)) + { + target.RemoveAurasByType(AuraType.PeriodicDamage, ObjectGuid.Empty, target.GetAura(SpellIds.PriestShadowWordDeath)); // Sw:D shall not be removed. + target.RemoveAurasByType(AuraType.PeriodicDamagePercent); + target.RemoveAurasByType(AuraType.PeriodicLeech); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ApplyAura)); + } +} + +[Script] // 27285 - Seed of Corruption (damage) +class spell_warl_seed_of_corruption : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.CorruptionDamage); + } + + void HandleHit(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.CorruptionDamage, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] +class spell_warl_seed_of_corruption_dummy : SpellScript +{ + void RemoveVisualMissile(ref WorldObject target) + { + target = null; + } + + void SelectTarget(List targets) + { + if (targets.Count < 2) + return; + + if (!GetExplTargetUnit().HasAura(GetSpellInfo().Id, GetCaster().GetGUID())) + { + // primary target doesn't have seed, keep it + targets.Clear(); + targets.Add(GetExplTargetUnit()); + } + else + { + // primary target has seed, select random other target with no seed + targets.RemoveAll(new UnitAuraCheck(true, GetSpellInfo().Id, GetCaster().GetGUID())); + if (!targets.Empty()) + targets.RandomResize(1); + else + targets.Add(GetExplTargetUnit()); + } + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(RemoveVisualMissile, 0, Targets.UnitTargetEnemy)); + OnObjectAreaTargetSelect.Add(new(SelectTarget, 1, Targets.UnitDestAreaEnemy)); + OnObjectAreaTargetSelect.Add(new(SelectTarget, 2, Targets.UnitDestAreaEnemy)); + } +} + +[Script] // 27243 - Seed of Corruption +class spell_warl_seed_of_corruption_dummy_aura : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SeedOfCorruptionDamage); + } + + void OnPeriodic(AuraEffect aurEff) + { + Unit caster = GetCaster(); + if (caster != null) + caster.CastSpell(GetTarget(), SpellIds.SeedOfCorruptionDamage, aurEff); + } + + void CalculateBuffer(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + amount = caster.SpellBaseDamageBonusDone(GetSpellInfo().GetSchoolMask()) * GetEffectInfo(0).CalcValue(caster) / 100; + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null) + return; + + Unit caster = GetCaster(); + if (caster == null) + return; + + if (damageInfo.GetAttacker() == null || damageInfo.GetAttacker() != caster) + return; + + // other seed explosions detonate this instantly, no matter what damage amount is + if (damageInfo.GetSpellInfo() == null || damageInfo.GetSpellInfo().Id != SpellIds.SeedOfCorruptionDamage) + { int amount = (int)(aurEff.GetAmount() - damageInfo.GetDamage()); if (amount > 0) { aurEff.SetAmount(amount); - return; - } - - Remove(); - - Unit caster = GetCaster(); - if (caster == null) - return; - - caster.CastSpell(eventInfo.GetActionTarget(), SpellIds.SeedOfCorruptionGeneric, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); - } - } - - [Script] // 686 - Shadow Bolt - class spell_warl_shadow_bolt : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.ShadowBoltEnergize); - } - - void HandleAfterCast() - { - GetCaster().CastSpell(GetCaster(), SpellIds.ShadowBoltEnergize, true); - } - - public override void Register() - { - AfterCast.Add(new(HandleAfterCast)); - } - } - - [Script] // 86121 - Soul Swap - class spell_warl_soul_swap : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.GlyphOfSoulSwap, SpellIds.SoulSwapCdMarker, SpellIds.SoulSwapOverride); - } - - void HandleHit(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), SpellIds.SoulSwapOverride, true); - GetHitUnit().CastSpell(GetCaster(), SpellIds.SoulSwapDotMarker, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); - } - } - - [Script] // 86211 - Soul Swap Override - Also acts as a dot container - class spell_warl_soul_swap_override : AuraScript - { - List _dotList = new(); - Unit _swapCaster; - - //! Forced to, pure virtual functions must have a body when linking - public override void Register() { } - - public void AddDot(uint id) { _dotList.Add(id); } - - public List GetDotList() { return _dotList; } - - public Unit GetOriginalSwapSource() { return _swapCaster; } - - public void SetOriginalSwapSource(Unit victim) { _swapCaster = victim; } - } - - [Script] //! Soul Swap Copy Spells - 92795 - Simply copies spell IDs. - class spell_warl_soul_swap_dot_marker : SpellScript - { - void HandleHit(uint effIndex) - { - Unit swapVictim = GetCaster(); - Unit warlock = GetHitUnit(); - if (warlock == null || swapVictim == null) - return; - - var appliedAuras = swapVictim.GetAppliedAuras(); - spell_warl_soul_swap_override swapSpellScript = null; - Aura swapOverrideAura = warlock.GetAura(SpellIds.SoulSwapOverride); - if (swapOverrideAura != null) - swapSpellScript = swapOverrideAura.GetScript(); - - if (swapSpellScript == null) - return; - - FlagArray128 classMask = GetEffectInfo().SpellClassMask; - - foreach (var (id, aurApp) in appliedAuras) - { - SpellInfo spellProto = aurApp.GetBase().GetSpellInfo(); - if (aurApp.GetBase().GetCaster() == warlock) - if (spellProto.SpellFamilyName == SpellFamilyNames.Warlock && (spellProto.SpellFamilyFlags & classMask)) - swapSpellScript.AddDot(id); - } - - swapSpellScript.SetOriginalSwapSource(swapVictim); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.Dummy)); - } - } - - [Script] // 86213 - Soul Swap Exhale - class spell_warl_soul_swap_exhale : SpellScript - { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SoulSwapModCost, SpellIds.SoulSwapOverride); - } - - SpellCastResult CheckCast() - { - Unit currentTarget = GetExplTargetUnit(); - Unit swapTarget = null; - Aura swapOverride = GetCaster().GetAura(SpellIds.SoulSwapOverride); - if (swapOverride != null) - { - spell_warl_soul_swap_override swapScript = swapOverride.GetScript(); - if (swapScript != null) - swapTarget = swapScript.GetOriginalSwapSource(); - } - - // Soul Swap Exhale can't be cast on the same target than Soul Swap - if (swapTarget != null && currentTarget != null && swapTarget == currentTarget) - return SpellCastResult.BadTargets; - - return SpellCastResult.SpellCastOk; - } - - void OnEffectHitTargetTemp(uint effIndex) - { - GetCaster().CastSpell(GetCaster(), SpellIds.SoulSwapModCost, true); - bool hasGlyph = GetCaster().HasAura(SpellIds.GlyphOfSoulSwap); - - List dotList = new(); - Unit swapSource = null; - Aura swapOverride = GetCaster().GetAura(SpellIds.SoulSwapOverride); - if (swapOverride != null) - { - spell_warl_soul_swap_override swapScript = swapOverride.GetScript(); - if (swapScript == null) + if (!GetTarget().HealthBelowPctDamaged(1, damageInfo.GetDamage())) return; - dotList = swapScript.GetDotList(); - swapSource = swapScript.GetOriginalSwapSource(); } + } - if (dotList.Empty()) - return; + Remove(); - foreach (var spellId in dotList) + caster.CastSpell(eventInfo.GetActionTarget(), SpellIds.SeedOfCorruptionDamage, aurEff); + } + + public override void Register() + { + OnEffectPeriodic.Add(new(OnPeriodic, 1, AuraType.PeriodicDamage)); + DoEffectCalcAmount.Add(new(CalculateBuffer, 2, AuraType.Dummy)); + OnEffectProc.Add(new(HandleProc, 2, AuraType.Dummy)); + } +} + +// 32863 - Seed of Corruption +// 36123 - Seed of Corruption +// 38252 - Seed of Corruption +// 39367 - Seed of Corruption +// 44141 - Seed of Corruption +// 70388 - Seed of Corruption +[Script] // Monster spells, triggered only on amount drop (not on death) +class spell_warl_seed_of_corruption_generic : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SeedOfCorruptionGeneric); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + int amount = (int)(aurEff.GetAmount() - damageInfo.GetDamage()); + if (amount > 0) + { + aurEff.SetAmount(amount); + return; + } + + Remove(); + + Unit caster = GetCaster(); + if (caster == null) + return; + + caster.CastSpell(eventInfo.GetActionTarget(), SpellIds.SeedOfCorruptionGeneric, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 17877 - Shadowburn +class spell_warl_shadowburn : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowburnEnergize) + && ValidateSpellEffect((spellInfo.Id, 3)); + } + + void HandleEnergize() + { + if (GetHitUnit().IsAlive()) + return; + + // killing target with current spell doesn't apply the aura (apply/remove scripts don't execute) + // but we can use the fact that it still gets created and immediately marked as removed to detect that case + Aura hitAura = GetHitAura(false, true); + if (hitAura == null || !hitAura.IsRemoved()) + return; + + TryEnergize(GetCaster()?.ToPlayer(), GetHitUnit(), GetSpellInfo(), GetSpell(), null); + } + + void CalcCritChance(Unit victim, ref float critChance) + { + if (victim.HealthBelowPct(GetEffectInfo(3).CalcValue(GetCaster()))) + critChance += GetEffectInfo(2).CalcValue(GetCaster()); + } + + public override void Register() + { + AfterHit.Add(new(HandleEnergize)); + OnCalcCritChance.Add(new(CalcCritChance)); + } + + public + static void TryEnergize(Player caster, Unit target, SpellInfo spellInfo, + Spell triggeringSpell, AuraEffect triggeringAura) + { + if (caster == null) + return; + + if (caster.IsHonorOrXPTarget(target)) + { + caster.CastSpell(caster, SpellIds.ShadowburnEnergize, new CastSpellExtraArgs() { - GetCaster().AddAura(spellId, GetHitUnit()); - if (!hasGlyph && swapSource != null) - swapSource.RemoveAurasDueToSpell(spellId); - } + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = triggeringSpell, + TriggeringAura = triggeringAura + }); - // Remove Soul Swap Exhale buff - GetCaster().RemoveAurasDueToSpell(SpellIds.SoulSwapOverride); - - if (hasGlyph) // Add a cooldown on Soul Swap if caster has the glyph - GetCaster().CastSpell(GetCaster(), SpellIds.SoulSwapCdMarker, false); - } - - public override void Register() - { - OnCheckCast.Add(new(CheckCast)); - OnEffectHitTarget.Add(new(OnEffectHitTargetTemp, 0, SpellEffectName.SchoolDamage)); + caster.GetSpellHistory().RestoreCharge(spellInfo.ChargeCategoryId); } } +} - [Script] // 29858 - Soulshatter - class spell_warl_soulshatter : SpellScript +[Script] +class spell_warl_shadowburn_aura : AuraScript +{ + void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode) { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SoulshatterEffect); - } + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) + return; - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - Unit target = GetHitUnit(); - if (target != null) - if (target.GetThreatManager().IsThreatenedBy(caster, true)) - caster.CastSpell(target, SpellIds.SoulshatterEffect, true); - } - - public override void Register() - { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + spell_warl_shadowburn.TryEnergize(GetCaster()?.ToPlayer(), GetTarget(), GetSpellInfo(), null, aurEff); } - [Script] // 366323 - Strengthen Pact - Succubus - class spell_warl_strengthen_pact_succubus : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SuccubusPact, SpellIds.SummonSuccubus); - } + AfterEffectRemove.Add(new(RemoveEffect, 1, AuraType.Dummy, AuraEffectHandleModes.Real)); + } +} - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - - caster.CastSpell(null, SpellIds.SuccubusPact, TriggerCastFlags.FullMask); - caster.CastSpell(null, SpellIds.SummonSuccubus, TriggerCastFlags.FullMask); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } +[Script] // 686 - Shadow Bolt +class spell_warl_shadow_bolt : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ShadowBoltEnergize); } - [Script] // 366325 - Strengthen Pact - Incubus - class spell_warl_strengthen_pact_incubus : SpellScript + void HandleAfterCast() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.IncubusPact, SpellIds.SummonIncubus); - } - - void HandleDummy(uint effIndex) - { - Unit caster = GetCaster(); - - caster.CastSpell(null, SpellIds.IncubusPact, TriggerCastFlags.FullMask); - caster.CastSpell(null, SpellIds.SummonIncubus, TriggerCastFlags.FullMask); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } + GetCaster().CastSpell(GetCaster(), SpellIds.ShadowBoltEnergize, true); } - [Script] // 366222 - Summon Sayaad - class spell_warl_summon_sayaad : SpellScript + public override void Register() { - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(SpellIds.SummonSuccubus, SpellIds.SummonIncubus); - } + AfterCast.Add(new(HandleAfterCast)); + } +} - void HandleDummy(uint effIndex) - { - GetCaster().CastSpell(null, RandomHelper.randChance(50) ? SpellIds.SummonSuccubus : SpellIds.SummonIncubus, TriggerCastFlags.FullMask); - } - - public override void Register() - { - OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); - } +[Script] // 422054 - Shadow Invocation +class spell_warl_shadow_invocation : AuraScript +{ + void HandleProc(ProcEventInfo eventInfo) + { + Unit caster = eventInfo.GetActor(); + Unit target = eventInfo.GetActionTarget(); + caster.m_Events.AddEventAtOffset(new BilescourgeBombersEvent(caster, caster.GetPosition(), target.GetPosition()), TimeSpan.FromSeconds(500)); } - // 37377 - Shadowflame - // 39437 - Shadowflame Hellfire and RoF - [Script("spell_warl_t4_2p_bonus_shadow", SpellIds.Flameshadow)] - [Script("spell_warl_t4_2p_bonus_fire", SpellIds.Shadowflame)] - class spell_warl_t4_2p_bonus : AuraScript + public override void Register() { - uint _triggerId; + OnProc.Add(new(HandleProc)); + } +} - public spell_warl_t4_2p_bonus(uint triggerId) - { - _triggerId = triggerId; - } - - public override bool Validate(SpellInfo spellInfo) - { - return ValidateSpellInfo(_triggerId); - } - - void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) - { - PreventDefaultAction(); - Unit caster = eventInfo.GetActor(); - caster.CastSpell(caster, _triggerId, aurEff); - } - - public override void Register() - { - OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); - } +[Script] // 452999 - Siphon Life +class spell_warl_siphon_life : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SiphonLifeHeal); } - [Script] // 316099 - Unstable Affliction - class spell_warl_unstable_affliction : AuraScript + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - public override bool Validate(SpellInfo spellInfo) + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + Unit caster = GetTarget(); + caster.CastSpell(caster, SpellIds.SiphonLifeHeal, new CastSpellExtraArgs(aurEff) + .AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount()))); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy)); + } +} + +[Script] // 6353 - Soul Fire +class spell_warl_soul_fire : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SoulFireEnergize, SpellIds.WitherTalent, SpellIds.WitherPeriodic, SpellIds.ImmolatePeriodic); + } + + void HandleTriggers(uint effIndex) + { + Unit caster = GetCaster(); + + caster.CastSpell(caster, SpellIds.SoulFireEnergize, new CastSpellExtraArgs() { - return ValidateSpellInfo(SpellIds.UnstableAfflictionDamage, SpellIds.UnstableAfflictionEnergize); + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + + uint periodicDamage = GetCaster().HasAura(SpellIds.WitherTalent) + ? SpellIds.WitherPeriodic + : SpellIds.ImmolatePeriodic; + caster.CastSpell(GetHitUnit(), periodicDamage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + OnEffectLaunchTarget.Add(new(HandleTriggers, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 86121 - Soul Swap +class spell_warl_soul_swap : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GlyphOfSoulSwap, SpellIds.SoulSwapCdMarker, SpellIds.SoulSwapOverride); + } + + void HandleHit(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.SoulSwapOverride, true); + GetHitUnit().CastSpell(GetCaster(), SpellIds.SoulSwapDotMarker, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.SchoolDamage)); + } +} + +[Script] // 86211 - Soul Swap Override - Also acts as a dot container +class spell_warl_soul_swap_override : AuraScript +{ + List _dotList = new(); + Unit _swapCaster; + + //! Forced to, pure virtual functions must have a body when linking + public override void Register() { } + + public void AddDot(uint id) { _dotList.Add(id); } + public List GetDotList() { return _dotList; } + public Unit GetOriginalSwapSource() { return _swapCaster; } + public void SetOriginalSwapSource(Unit victim) { _swapCaster = victim; } +} + +[Script] //! Soul Swap Copy Spells - 92795 - Simply copies spell IDs. +class spell_warl_soul_swap_dot_marker : SpellScript +{ + void HandleHit(uint effIndex) + { + Unit swapVictim = GetCaster(); + Unit warlock = GetHitUnit(); + if (warlock == null || swapVictim == null) + return; + + var appliedAuras = swapVictim.GetAppliedAuras(); + spell_warl_soul_swap_override swapSpellScript = null; + Aura swapOverrideAura = warlock.GetAura(SpellIds.SoulSwapOverride); + if (swapOverrideAura != null) + swapSpellScript = swapOverrideAura.GetScript(); + + if (swapSpellScript == null) + return; + + FlagArray128 classMask = GetEffectInfo().SpellClassMask; + + foreach (var (key, app) in appliedAuras) + { + SpellInfo spellProto = app.GetBase().GetSpellInfo(); + if (app.GetBase().GetCaster() == warlock) + if (spellProto.SpellFamilyName == SpellFamilyNames.Warlock && (spellProto.SpellFamilyFlags & classMask)) + swapSpellScript.AddDot(key); } - void HandleDispel(DispelInfo dispelInfo) + swapSpellScript.SetOriginalSwapSource(swapVictim); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 86213 - Soul Swap Exhale +class spell_warl_soul_swap_exhale : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SoulSwapModCost, SpellIds.SoulSwapOverride); + } + + SpellCastResult CheckCast() + { + Unit currentTarget = GetExplTargetUnit(); + Unit swapTarget = null; + Aura swapOverride = GetCaster().GetAura(SpellIds.SoulSwapOverride); + if (swapOverride != null) { - Unit caster = GetCaster(); - if (caster == null) + spell_warl_soul_swap_override swapScript = swapOverride.GetScript(); + if (swapScript != null) + swapTarget = swapScript.GetOriginalSwapSource(); + } + + // Soul Swap Exhale can't be cast on the same target than Soul Swap + if (swapTarget != null && currentTarget != null && swapTarget == currentTarget) + return SpellCastResult.BadTargets; + + return SpellCastResult.SpellCastOk; + } + + void OnEffectHit(uint effIndex) + { + GetCaster().CastSpell(GetCaster(), SpellIds.SoulSwapModCost, true); + bool hasGlyph = GetCaster().HasAura(SpellIds.GlyphOfSoulSwap); + + List dotList = new(); + Unit swapSource = null; + Aura swapOverride = GetCaster().GetAura(SpellIds.SoulSwapOverride); + if (swapOverride != null) + { + spell_warl_soul_swap_override swapScript = swapOverride.GetScript(); + if (swapScript == null) return; - - AuraEffect removedEffect = GetEffect(1); - if (removedEffect == null) - return; - - int damage = (int)(GetEffectInfo(0).CalcValue(caster, null, GetUnitOwner()) / 100.0f * removedEffect.CalculateEstimatedAmount(caster, removedEffect.GetAmount())); - caster.CastSpell(dispelInfo.GetDispeller(), SpellIds.UnstableAfflictionDamage, new CastSpellExtraArgs() - .AddSpellMod(SpellValueMod.BasePoint0, damage) - .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); + dotList = swapScript.GetDotList(); + swapSource = swapScript.GetOriginalSwapSource(); } - void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + if (dotList.Empty()) + return; + + foreach (var spellId in dotList) { - if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) - return; - - GetCaster().CastSpell(GetCaster(), SpellIds.UnstableAfflictionEnergize, true); + GetCaster().AddAura(spellId, GetHitUnit()); + if (!hasGlyph && swapSource != null) + swapSource.RemoveAurasDueToSpell(spellId); } - public override void Register() - { - AfterDispel.Add(new(HandleDispel)); - OnEffectRemove.Add(new(HandleRemove, 1, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); - } + // Remove Soul Swap Exhale buff + GetCaster().RemoveAurasDueToSpell(SpellIds.SoulSwapOverride); + + if (hasGlyph) // Add a cooldown on Soul Swap if caster has the glyph + GetCaster().CastSpell(GetCaster(), SpellIds.SoulSwapCdMarker, false); } - // 5740 - Rain of Fire - [Script] /// Updated 11.0.2 - class spell_warl_rain_of_fire : AuraScript + public override void Register() { - void HandleDummyTick(AuraEffect aurEff) - { - List rainOfFireAreaTriggers = GetTarget().GetAreaTriggers(SpellIds.RainOfFire); - List targetsInRainOfFire = new(); + OnCheckCast.Add(new(CheckCast)); + OnEffectHitTarget.Add(new(OnEffectHit, 0, SpellEffectName.SchoolDamage)); + } +} - foreach (AreaTrigger rainOfFireAreaTrigger in rainOfFireAreaTriggers) +[Script] // 29858 - Soulshatter +class spell_warl_soulshatter : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SoulshatterEffect); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + if (target != null) + if (target.GetThreatManager().IsThreatenedBy(caster, true)) + caster.CastSpell(target, SpellIds.SoulshatterEffect, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 366323 - Strengthen Pact - Succubus +class spell_warl_strengthen_pact_succubus : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SuccubusPact, SpellIds.SummonSuccubus); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + + caster.CastSpell(null, SpellIds.SuccubusPact, TriggerCastFlags.FullMask); + caster.CastSpell(null, SpellIds.SummonSuccubus, TriggerCastFlags.FullMask); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 366325 - Strengthen Pact - Incubus +class spell_warl_strengthen_pact_incubus : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IncubusPact, SpellIds.SummonIncubus); + } + + void HandleDummy(uint effIndex) + { + Unit caster = GetCaster(); + + caster.CastSpell(null, SpellIds.IncubusPact, TriggerCastFlags.FullMask); + caster.CastSpell(null, SpellIds.SummonIncubus, TriggerCastFlags.FullMask); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +[Script] // 366222 - Summon Sayaad +class spell_warl_summon_sayaad : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SummonSuccubus, SpellIds.SummonIncubus); + } + + void HandleDummy(uint effIndex) + { + GetCaster().CastSpell(null, RandomHelper.randChance(50) ? SpellIds.SummonSuccubus : SpellIds.SummonIncubus, TriggerCastFlags.FullMask); + } + + public override void Register() + { + OnEffectHit.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + } +} + +// 37377 - Shadowflame +// 39437 - Shadowflame Hellfire and RoF +[Script("spell_warl_t4_2p_bonus_shadow", SpellIds.Flameshadow)] +[Script("spell_warl_t4_2p_bonus_fire", SpellIds.Shadowflame)] +class spell_warl_t4_2p_bonus(uint trigger) : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(trigger); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + Unit caster = eventInfo.GetActor(); + caster.CastSpell(caster, trigger, aurEff); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); + } +} + +[Script] // 316099 - Unstable Affliction +class spell_warl_unstable_affliction : AuraScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.UnstableAfflictionDamage, SpellIds.UnstableAfflictionEnergize); + } + + void HandleDispel(DispelInfo dispelInfo) + { + Unit caster = GetCaster(); + if (caster == null) + return; + + AuraEffect removedEffect = GetEffect(1); + if (removedEffect == null) + return; + + int damage = (int)(GetEffectInfo(0).CalcValue(caster, null, GetUnitOwner()) / 100.0f * removedEffect.CalculateEstimatedAmount(caster, removedEffect.GetAmount()).Value); + caster.CastSpell(dispelInfo.GetDispeller(), SpellIds.UnstableAfflictionDamage, new CastSpellExtraArgs() + .AddSpellMod(SpellValueMod.BasePoint0, damage) + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)); + } + + void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode) + { + if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Death) + return; + + GetCaster().CastSpell(GetCaster(), SpellIds.UnstableAfflictionEnergize, true); + } + + public override void Register() + { + AfterDispel.Add(new(HandleDispel)); + OnEffectRemove.Add(new(HandleRemove, 1, AuraType.PeriodicDamage, AuraEffectHandleModes.Real)); + } +} + +[Script] // 278350 - Vile Taint +class spell_warl_vile_taint : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Agony, SpellIds.CurseOfExhaustion, SpellIds.VileTaintDamage); + } + + void HandleScriptEffect(uint effIndex) + { + Unit caster = GetCaster(); + CastSpellTargetArg target = GetHitUnit(); + + CastSpellExtraArgs args = new(); + args.SetTriggerFlags(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost + | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); + args.SetTriggeringSpell(GetSpell()); + + caster.CastSpell(target, SpellIds.Agony, args); + caster.CastSpell(target, SpellIds.CurseOfExhaustion, args); + caster.CastSpell(target, SpellIds.VileTaintDamage, args); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.Dummy)); + } +} + +// Called by 980 - Agony +[Script] // 453034 - Volatile Agony +class spell_warl_volatile_agony : SpellScript +{ + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.VolatileAgonyTalent, SpellIds.VolatileAgonyDamage); + } + + void TriggerExplosion() + { + Unit caster = GetCaster(); + Unit target = GetHitUnit(); + + AuraEffect volatileAgony = caster.GetAuraEffect(SpellIds.VolatileAgonyTalent, 0); + if (volatileAgony != null) + { + Aura agonyAura = target.GetAura(GetSpellInfo().Id, caster.GetGUID()); + if (agonyAura != null) { - List insideTargets = rainOfFireAreaTrigger.GetInsideUnits(); - targetsInRainOfFire.AddRange(insideTargets); + TimeSpan maxAgonyDuration = TimeSpan.FromSeconds(volatileAgony.GetAmount()); + if (TimeSpan.FromSeconds(agonyAura.GetDuration()) <= maxAgonyDuration) + caster.CastSpell(target, SpellIds.VolatileAgonyDamage, new CastSpellExtraArgs() + .SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError) + .SetTriggeringSpell(GetSpell())); } - - foreach (ObjectGuid insideTargetGuid in targetsInRainOfFire) - { - Unit insideTarget = ObjAccessor.GetUnit(GetTarget(), insideTargetGuid); - if (insideTarget != null) - if (!GetTarget().IsFriendlyTo(insideTarget)) - GetTarget().CastSpell(insideTarget, SpellIds.RainOfFireDamage, true); - } - } - - public override void Register() - { - OnEffectPeriodic.Add(new(HandleDummyTick, 2, AuraType.PeriodicDummy)); } } -} \ No newline at end of file + + public override void Register() + { + OnHit.Add(new(TriggerExplosion)); + } +} diff --git a/Source/Scripts/Spells/Warrior.cs b/Source/Scripts/Spells/Warrior.cs index 9e540c36a..eec7f9048 100644 --- a/Source/Scripts/Spells/Warrior.cs +++ b/Source/Scripts/Spells/Warrior.cs @@ -1,66 +1,233 @@ // Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +// Licensed under the Gnu General Public License. See License file in the project root for full license information. using Framework.Constants; +using Framework.Dynamic; using Game.Entities; using Game.Movement; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; -using System.Numerics; -using static Global; namespace Scripts.Spells.Warrior { struct SpellIds { + public const uint Avatar = 107574; + public const uint Bladestorm = 227847; public const uint BladestormPeriodicWhirlwind = 50622; public const uint BloodthirstHeal = 117313; public const uint Charge = 34846; - public const uint ChargeEffect = 218104; - public const uint ChargeEffectBlazingTrail = 198337; - public const uint ChargePauseRageDecay = 109128; + public const uint ChargeDropFirePeriodic = 126661; + public const uint ChargeEffect = 198337; public const uint ChargeRootEffect = 105771; - public const uint ChargeSlowEffect = 236027; + public const uint ColdSteelHotBloodTalent = 383959; public const uint ColossusSmash = 167105; public const uint ColossusSmashAura = 208086; public const uint CriticalThinkingEnergize = 392776; + public const uint DeftExperience = 383295; public const uint Execute = 20647; + public const uint Enrage = 184362; + public const uint FrenziedEnrage = 383848; + public const uint FrenzyTalent = 335077; + public const uint FrenzyBuff = 335082; + public const uint FreshMeatDebuff = 316044; + public const uint FreshMeatTalent = 215568; public const uint FueledByViolenceHeal = 383104; public const uint GlyphOfTheBlazingTrail = 123779; public const uint GlyphOfHeroicLeap = 159708; public const uint GlyphOfHeroicLeapBuff = 133278; + public const uint GushingWound = 385042; public const uint HeroicLeapJump = 178368; public const uint IgnorePain = 190456; + public const uint ImprovedRagingBlow = 383854; + public const uint ImprovedWhirlwind = 12950; + public const uint IntimidatingShoutMenaceAoe = 316595; + public const uint InvigoratingFury = 385174; + public const uint InvigoratingFuryTalent = 383468; public const uint InForTheKill = 248621; public const uint InForTheKillHaste = 248622; public const uint ImpendingVictory = 202168; public const uint ImpendingVictoryHeal = 202166; public const uint ImprovedHeroicLeap = 157449; public const uint MortalStrike = 12294; - public const uint MortalWounds = 213667; + public const uint MortalWounds = 115804; + public const uint PowerfulEnrage = 440277; public const uint RallyingCry = 97463; + public const uint Ravager = 228920; + public const uint Recklessness = 1719; + public const uint RumblingEarth = 275339; public const uint ShieldBlockAura = 132404; public const uint ShieldChargeEffect = 385953; public const uint ShieldSlam = 23922; public const uint ShieldSlamMarker = 224324; + public const uint ShieldWall = 871; public const uint Shockwave = 46968; public const uint ShockwaveStun = 132168; + public const uint SlaughteringStrikes = 388004; + public const uint SlaughteringStrikesBuff = 393931; public const uint Stoicism = 70845; public const uint StormBoltStun = 132169; + public const uint StormBolts = 436162; public const uint Strategist = 384041; + public const uint SuddenDeath = 280721; + public const uint SuddenDeathBuff = 280776; public const uint SweepingStrikesExtraAttack1 = 12723; public const uint SweepingStrikesExtraAttack2 = 26654; public const uint Taunt = 355; + public const uint TitanicRage = 394329; public const uint TraumaEffect = 215537; + public const uint ViciousContempt = 383885; public const uint Victorious = 32216; public const uint VictoryRushHeal = 118779; + public const uint Warbreaker = 262161; + public const uint WhirlwindCleaveAura = 85739; + public const uint WhirlwindEnergize = 280715; + public const uint WrathAndFury = 392936; public const uint VisualBlazingCharge = 26423; } - [Script] // 23881 - Bloodthirst + struct WarriorMisc + { + public static void ApplyWhirlwindCleaveAura(Player caster, Difficulty difficulty, Spell triggeringSpell) + { + SpellInfo whirlwindCleaveAuraInfo = Global.SpellMgr.GetSpellInfo(SpellIds.WhirlwindCleaveAura, difficulty); + int stackAmount = (int)(whirlwindCleaveAuraInfo.StackAmount); + caster.ApplySpellMod(whirlwindCleaveAuraInfo, SpellModOp.MaxAuraStacks, ref stackAmount); + + caster.CastSpell(null, SpellIds.WhirlwindCleaveAura, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = triggeringSpell, + SpellValueOverrides = { new(SpellValueMod.AuraStack, stackAmount) } + }); + } + } + + [Script] // 152278 - Anger Management + class spell_warr_anger_management_proc : AuraScript + { + static TimeSpan CooldownReduction = TimeSpan.FromSeconds(1); + static uint[] ArmsSpellIds = [SpellIds.ColossusSmash, SpellIds.Warbreaker, SpellIds.Bladestorm, SpellIds.Ravager]; + static uint[] FurySpellIds = [SpellIds.Recklessness, SpellIds.Bladestorm, SpellIds.Ravager]; + static uint[] ProtectionSpellIds = [SpellIds.Avatar, SpellIds.ShieldWall]; + + static bool ValidateProc(AuraEffect aurEff, ProcEventInfo eventInfo, ChrSpecialization spec) + { + if (aurEff.GetAmount() == 0) + return false; + + Player player = eventInfo.GetActor().ToPlayer(); + if (player == null) + return false; + + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + if (procSpell.GetPowerTypeCostAmount(PowerType.Rage) <= 0) + return false; + + return player.GetPrimarySpecialization() == spec; + } + + static bool CheckArmsProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + if (!ValidateProc(aurEff, eventInfo, ChrSpecialization.WarriorArms)) + return false; + + // exclude non-attacks such as Ignore Pain + if (!eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Warrior, new FlagArray128(0x100, 0x0, 0x0, 0x0))) + return false; + + return true; + } + + static bool CheckFuryProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return ValidateProc(aurEff, eventInfo, ChrSpecialization.WarriorFury); + } + + static bool CheckProtectionProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + return ValidateProc(aurEff, eventInfo, ChrSpecialization.WarriorProtection); + } + + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ColossusSmash, SpellIds.Bladestorm, SpellIds.Ravager, SpellIds.Warbreaker, SpellIds.Recklessness, SpellIds.Avatar, SpellIds.ShieldWall); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo, uint[] spellIds) + { + int rageCost = (int)eventInfo.GetProcSpell().GetPowerTypeCostAmount(PowerType.Rage) / 10; // db values are 10x the actual rage cost + float multiplier = (float)(rageCost) / (float)(aurEff.GetAmount()); + TimeSpan cooldownMod = -(multiplier * CooldownReduction); + + foreach (uint spellId in spellIds) + GetTarget().GetSpellHistory().ModifyCooldown(spellId, cooldownMod); + } + + void OnProcArms(AuraEffect aurEff, ProcEventInfo eventInfo) + { + HandleProc(aurEff, eventInfo, ArmsSpellIds); + } + + void OnProcFury(AuraEffect aurEff, ProcEventInfo eventInfo) + { + HandleProc(aurEff, eventInfo, FurySpellIds); + } + + void OnProcProtection(AuraEffect aurEff, ProcEventInfo eventInfo) + { + HandleProc(aurEff, eventInfo, ProtectionSpellIds); + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckArmsProc, 0, AuraType.Dummy)); + DoCheckEffectProc.Add(new(CheckProtectionProc, 1, AuraType.Dummy)); + DoCheckEffectProc.Add(new(CheckFuryProc, 2, AuraType.Dummy)); + + OnEffectProc.Add(new(OnProcArms, 0, AuraType.Dummy)); + OnEffectProc.Add(new(OnProcProtection, 1, AuraType.Dummy)); + OnEffectProc.Add(new(OnProcFury, 2, AuraType.Dummy)); + } + } + + [Script] // 392536 - Ashen Juggernaut + class spell_warr_ashen_juggernaut : AuraScript + { + static bool CheckProc(ProcEventInfo eventInfo) + { + // should only proc on primary target + return eventInfo.GetActionTarget() == eventInfo.GetProcSpell().m_targets.GetUnitTarget(); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + } + } + + [Script] // 107574 - Avatar + class spell_warr_avatar : SpellScript + { + void HandleRemoveImpairingAuras(uint effIndex) + { + GetCaster().RemoveMovementImpairingAuras(true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleRemoveImpairingAuras, 5, SpellEffectName.ScriptEffect)); + } + } + + // 23881 - Bloodthirst + [Script] // 335096 - Bloodbath class spell_warr_bloodthirst : SpellScript { public override bool Validate(SpellInfo spellInfo) @@ -68,14 +235,21 @@ namespace Scripts.Spells.Warrior return ValidateSpellInfo(SpellIds.BloodthirstHeal); } - void HandleDummy(uint effIndex) + void CastHeal(uint effIndex) { - GetCaster().CastSpell(GetCaster(), SpellIds.BloodthirstHeal, true); + if (GetHitUnit() != GetExplTargetUnit()) + return; + + GetCaster().CastSpell(GetCaster(), SpellIds.BloodthirstHeal, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } public override void Register() { - OnEffectHit.Add(new(HandleDummy, 3, SpellEffectName.Dummy)); + OnEffectHitTarget.Add(new(CastHeal, 0, SpellEffectName.SchoolDamage)); } } @@ -118,16 +292,16 @@ namespace Scripts.Spells.Warrior { public override bool Validate(SpellInfo spellInfo) { - return ValidateSpellInfo(SpellIds.ChargeEffect, SpellIds.ChargeEffectBlazingTrail); + return ValidateSpellInfo(SpellIds.ChargeEffect); } void HandleDummy(uint effIndex) { - uint spellId = SpellIds.ChargeEffect; - if (GetCaster().HasAura(SpellIds.GlyphOfTheBlazingTrail)) - spellId = SpellIds.ChargeEffectBlazingTrail; - - GetCaster().CastSpell(GetHitUnit(), spellId, true); + GetCaster().CastSpell(GetHitUnit(), SpellIds.ChargeEffect, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } public override void Register() @@ -142,39 +316,53 @@ namespace Scripts.Spells.Warrior void DropFireVisual(AuraEffect aurEff) { PreventDefaultAction(); - if (GetTarget().IsSplineEnabled()) + + Unit target = GetTarget(); + if (target.IsSplineEnabled()) { - for (int i = 0; i < 5; ++i) + var from = target.MoveSpline.ComputePosition(); + var to = target.MoveSpline.ComputePosition(aurEff.GetPeriod()); + + int fireCount = (int)Math.Round((to - from).Length()); + + for (int i = 0; i < fireCount; ++i) { - int timeOffset = (int)(6 * i * aurEff.GetPeriod() / 25); - Vector4 loc = GetTarget().MoveSpline.ComputePosition(timeOffset); - GetTarget().SendPlaySpellVisual(new Position(loc.X, loc.Y, loc.Z), SpellIds.VisualBlazingCharge, 0, 0, 1.0f, true); + int timeOffset = i * aurEff.GetPeriod() / fireCount; + var loc = target.MoveSpline.ComputePosition(timeOffset); + target.SendPlaySpellVisual(new Position(loc.X, loc.Y, loc.Z), SpellIds.VisualBlazingCharge, 0, 0, 1.0f, true); } } } public override void Register() { - OnEffectPeriodic.Add(new(DropFireVisual, 0, AuraType.PeriodicTriggerSpell)); + OnEffectPeriodic.Add(new(DropFireVisual, 0, AuraType.PeriodicDummy)); } } - // 198337 - Charge Effect (dropping Blazing Trail) - [Script] // 218104 - Charge Effect + [Script] // 198337 - Charge Effect class spell_warr_charge_effect : SpellScript { public override bool Validate(SpellInfo spellInfo) { - return ValidateSpellInfo(SpellIds.ChargePauseRageDecay, SpellIds.ChargeRootEffect, SpellIds.ChargeSlowEffect); + return ValidateSpellInfo(SpellIds.ChargeRootEffect, SpellIds.ChargeDropFirePeriodic); } void HandleCharge(uint effIndex) { Unit caster = GetCaster(); Unit target = GetHitUnit(); - caster.CastSpell(caster, SpellIds.ChargePauseRageDecay, new CastSpellExtraArgs(TriggerCastFlags.FullMask).AddSpellMod(SpellValueMod.BasePoint0, 0)); - caster.CastSpell(target, SpellIds.ChargeRootEffect, true); - caster.CastSpell(target, SpellIds.ChargeSlowEffect, true); + + CastSpellExtraArgs args = new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.FullMask & ~TriggerCastFlags.CastDirectly, + TriggeringSpell = GetSpell() + }; + + if (caster.HasAura(SpellIds.GlyphOfTheBlazingTrail)) + caster.CastSpell(target, SpellIds.ChargeDropFirePeriodic, args); + + caster.CastSpell(target, SpellIds.ChargeRootEffect, args); } public override void Register() @@ -183,6 +371,37 @@ namespace Scripts.Spells.Warrior } } + // 23881 - Bloodthirst + [Script] // 335096 - Bloodbath + class spell_warr_cold_steel_hot_blood_bloodthirst : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.GushingWound, SpellIds.ColdSteelHotBloodTalent); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ColdSteelHotBloodTalent); + } + + void CastGushingWound(uint effIndex) + { + if (!IsHitCrit()) + return; + + GetCaster().CastSpell(GetHitUnit(), SpellIds.GushingWound, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(CastGushingWound, 0, SpellEffectName.SchoolDamage)); + } + } + // 167105 - Colossus Smash [Script] // 262161 - Warbreaker class spell_warr_colossus_smash : SpellScript @@ -192,7 +411,7 @@ namespace Scripts.Spells.Warrior public override bool Validate(SpellInfo spellInfo) { return ValidateSpellInfo(SpellIds.ColossusSmashAura, SpellIds.InForTheKill, SpellIds.InForTheKillHaste) - && ValidateSpellEffect((SpellIds.InForTheKill, 2)); + && ValidateSpellEffect((SpellIds.InForTheKill, 2)); } void HandleHit() @@ -204,7 +423,7 @@ namespace Scripts.Spells.Warrior if (caster.HasAura(SpellIds.InForTheKill)) { - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.InForTheKill, Difficulty.None); + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.InForTheKill, Difficulty.None); if (spellInfo != null) { if (target.HealthBelowPct(spellInfo.GetEffect(2).CalcValue(caster))) @@ -216,7 +435,7 @@ namespace Scripts.Spells.Warrior void HandleAfterCast() { Unit caster = GetCaster(); - SpellInfo spellInfo = SpellMgr.GetSpellInfo(SpellIds.InForTheKill, Difficulty.None); + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.InForTheKill, Difficulty.None); if (spellInfo == null) return; @@ -244,7 +463,7 @@ namespace Scripts.Spells.Warrior void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) { - int? rageCost = eventInfo.GetProcSpell().GetPowerTypeCostAmount(PowerType.Rage); + var rageCost = eventInfo.GetProcSpell().GetPowerTypeCostAmount(PowerType.Rage); if (rageCost.HasValue) GetTarget().CastSpell(null, SpellIds.CriticalThinkingEnergize, new CastSpellExtraArgs(TriggerCastFlags.FullMask) .AddSpellMod(SpellValueMod.BasePoint0, MathFunctions.CalculatePct(rageCost.Value, aurEff.GetAmount()))); @@ -256,6 +475,41 @@ namespace Scripts.Spells.Warrior } } + // 383295 - Deft Experience (attached to 23881 - Bloodthirst) + [Script] // 383295 - Deft Experience (attached to 335096 - Bloodbath) + class spell_warr_deft_experience : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.DeftExperience, 1)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.DeftExperience); + } + + void HandleDeftExperience(uint effIndex) + { + if (GetHitUnit() != GetExplTargetUnit()) + return; + + Unit caster = GetCaster(); + Aura enrageAura = caster.GetAura(SpellIds.Enrage); + if (enrageAura != null) + { + AuraEffect aurEff = caster.GetAuraEffect(SpellIds.DeftExperience, 1); + if (aurEff != null) + enrageAura.SetDuration(enrageAura.GetDuration() + aurEff.GetAmount()); + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleDeftExperience, 0, SpellEffectName.SchoolDamage)); + } + } + [Script] // 236279 - Devastator class spell_warr_devastator : AuraScript { @@ -264,7 +518,7 @@ namespace Scripts.Spells.Warrior return ValidateSpellEffect((spellInfo.Id, 1)) && ValidateSpellInfo(SpellIds.ShieldSlam, SpellIds.ShieldSlamMarker); } - void OnProcSpell(AuraEffect aurEff, ProcEventInfo eventInfo) + void OnProc(AuraEffect aurEff, ProcEventInfo eventInfo) { if (GetTarget().GetSpellHistory().HasCooldown(SpellIds.ShieldSlam)) { @@ -278,14 +532,235 @@ namespace Scripts.Spells.Warrior public override void Register() { - OnEffectProc.Add(new(OnProcSpell, 0, AuraType.ProcTriggerSpell)); + OnEffectProc.Add(new(OnProc, 0, AuraType.ProcTriggerSpell)); + } + } + + [Script] // 184361 - Enrage + class spell_warr_enrage_proc : AuraScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FreshMeatTalent, SpellIds.FreshMeatDebuff); + } + + static bool CheckRampageProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null || !spellInfo.IsAffected(SpellFamilyNames.Warrior, new FlagArray128(0x0, 0x0, 0x0, 0x8000000))) // Rampage + return false; + + return true; + } + + static bool IsBloodthirst(SpellInfo spellInfo) + { + // Bloodthirst/Bloodbath + return spellInfo.IsAffected(SpellFamilyNames.Warrior, new FlagArray128(0x0, 0x400)); + } + + static bool CheckBloodthirstProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + SpellInfo spellInfo = eventInfo.GetSpellInfo(); + if (spellInfo == null || !IsBloodthirst(spellInfo)) + return false; + + // Fresh Meat talent handling + Unit actor = eventInfo.GetActor(); + if (actor != null) + { + if (actor.HasAura(SpellIds.FreshMeatTalent)) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return false; + + Unit target = procSpell.m_targets.GetUnitTarget(); + if (target == null) + return false; + + if (!target.HasAura(SpellIds.FreshMeatDebuff, actor.GetGUID())) + return true; + } + } + + return RandomHelper.randChance(aurEff.GetAmount()); + } + + void HandleProc(ProcEventInfo eventInfo) + { + PreventDefaultAction(); + + Unit auraTarget = GetTarget(); + + auraTarget.CastSpell(null, SpellIds.Enrage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = eventInfo.GetProcSpell() + }); + + // Fresh Meat talent handling + if (auraTarget.HasAura(SpellIds.FreshMeatTalent)) + { + Spell procSpell = eventInfo.GetProcSpell(); + if (procSpell == null) + return; + + if (!IsBloodthirst(procSpell.GetSpellInfo())) + return; + + Unit bloodthirstTarget = procSpell.m_targets.GetUnitTarget(); + if (bloodthirstTarget != null) + if (!bloodthirstTarget.HasAura(SpellIds.FreshMeatDebuff, auraTarget.GetGUID())) + auraTarget.CastSpell(bloodthirstTarget, SpellIds.FreshMeatDebuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); + } + } + + public override void Register() + { + DoCheckEffectProc.Add(new(CheckRampageProc, 0, AuraType.Dummy)); + DoCheckEffectProc.Add(new(CheckBloodthirstProc, 1, AuraType.Dummy)); + OnProc.Add(new(HandleProc)); + } + } + + [Script] // 260798 - Execute (Arms, Protection) + class spell_warr_execute_damage : SpellScript + { + static void CalculateExecuteDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damageOrHealing, ref int flatMod, ref float pctMod) + { + // tooltip has 2 multiplier hardcoded in it $damage=${2.0*$260798s1} + pctMod *= 2.0f; + } + + public override void Register() + { + CalcDamage.Add(new(CalculateExecuteDamage)); + } + } + + [Script] // 383848 - Frenzied Enrage (attached to 184362 - Enrage) + class spell_warr_frenzied_enrage : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FrenziedEnrage) + && ValidateSpellEffect((spellInfo.Id, 1)) + && spellInfo.GetEffect(0).IsAura(AuraType.MeleeSlow) + && spellInfo.GetEffect(1).IsAura(AuraType.ModIncreaseSpeed); + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.FrenziedEnrage); + } + + void HandleFrenziedEnrage(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(HandleFrenziedEnrage, 0, Targets.UnitCaster)); + OnObjectTargetSelect.Add(new(HandleFrenziedEnrage, 1, Targets.UnitCaster)); + } + } + + [Script] // 335082 - frenzy + class spell_warr_frenzy : AuraScript + { + ObjectGuid _targetGuid; + + public void SetTargetGuid(ObjectGuid guid) { _targetGuid = guid; } + + public ObjectGuid GetTarGetGUID() { return _targetGuid; } + + public override void Register() { } + } + + [Script] // 335077 - Frenzy (attached to 184367 - Rampage) + class spell_warr_frenzy_rampage : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.FrenzyBuff, SpellIds.FrenzyTalent); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.FrenzyTalent); + } + + void HandleAfterCast(uint effIndex) + { + Unit caster = GetCaster(); + Unit hitUnit = GetHitUnit(); + + if (hitUnit != GetExplTargetUnit()) + return; + + caster.CastSpell(null, SpellIds.FrenzyBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + + Aura frenzyAura = caster.GetAura(SpellIds.FrenzyBuff); + if (frenzyAura != null) + { + spell_warr_frenzy script = frenzyAura.GetScript(); + if (script != null) + { + if (!script.GetTarGetGUID().IsEmpty() && script.GetTarGetGUID() != hitUnit.GetGUID()) + frenzyAura.SetStackAmount(1); + + script.SetTargetGuid(hitUnit.GetGUID()); + } + } + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleAfterCast, 0, SpellEffectName.Dummy)); + } + } + + [Script] // 440277 - Powerful Enrage (attached to 184362 - Enrage) + class spell_warr_powerful_enrage : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.PowerfulEnrage) + && ValidateSpellEffect((spellInfo.Id, 4)) + && spellInfo.GetEffect(3).IsAura(AuraType.AddPctModifier) && spellInfo.GetEffect(3).MiscValue == (int)SpellModOp.HealingAndDamage + && spellInfo.GetEffect(4).IsAura(AuraType.AddPctModifier) && spellInfo.GetEffect(4).MiscValue == (int)SpellModOp.PeriodicHealingAndDamage; + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.PowerfulEnrage); + } + + void HandlePowerfulEnrage(ref WorldObject target) + { + target = null; + } + + public override void Register() + { + OnObjectTargetSelect.Add(new(HandlePowerfulEnrage, 3, Targets.UnitCaster)); + OnObjectTargetSelect.Add(new(HandlePowerfulEnrage, 4, Targets.UnitCaster)); } } [Script] // 383103 - Fueled by Violence class spell_warr_fueled_by_violence : AuraScript { - uint _nextHealAmount = 0; + uint _nextHealAmount; public override bool Validate(SpellInfo spellInfo) { @@ -343,9 +818,9 @@ namespace Scripts.Spells.Warrior generatedPath.SetPathLengthLimit(range); bool result = generatedPath.CalculatePath(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), false); - if (generatedPath.GetPathType().HasFlag(PathType.Short)) + if (generatedPath.GetPathType().HasAnyFlag(PathType.Short)) return SpellCastResult.OutOfRange; - else if (!result || generatedPath.GetPathType().HasFlag(PathType.NoPath)) + else if (!result || generatedPath.GetPathType().HasAnyFlag(PathType.NoPath)) return SpellCastResult.NoPath; } else if (dest.GetPositionZ() > GetCaster().GetPositionZ() + 4.0f) @@ -414,6 +889,51 @@ namespace Scripts.Spells.Warrior } } + [Script] // 12950 - Improved Whirlwind (attached to 190411 - Whirlwind) + class spell_improved_whirlwind : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImprovedWhirlwind, SpellIds.WhirlwindCleaveAura) + && ValidateSpellEffect((spellInfo.Id, 2), (SpellIds.WhirlwindEnergize, 0)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ImprovedWhirlwind); + } + + void HandleHit(uint effIndex) + { + long targetsHit = GetUnitTargetCountForEffect(0); + if (targetsHit == 0) + return; + + Player caster = GetCaster().ToPlayer(); + if (caster == null) + return; + + int ragePerTarget = GetEffectValue(); + int baseRage = GetEffectInfo(0).CalcValue(); + int maxRage = baseRage + (ragePerTarget * GetEffectInfo(2).CalcValue()); + int rageGained = (int)Math.Min(baseRage + (targetsHit * ragePerTarget), maxRage); + + caster.CastSpell(null, SpellIds.WhirlwindEnergize, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell(), + SpellValueOverrides = { new(SpellValueMod.BasePoint0, rageGained * 10) } + }); + + WarriorMisc.ApplyWhirlwindCleaveAura(caster, GetCastDifficulty(), GetSpell()); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleHit, 1, SpellEffectName.Dummy)); + } + } + [Script] // 5246 - Intimidating Shout class spell_warr_intimidating_shout : SpellScript { @@ -422,10 +942,83 @@ namespace Scripts.Spells.Warrior unitList.Remove(GetExplTargetWorldObject()); } + void ClearTargets(List unitList) + { + // This is used in effect 3, which is an Aoe Root effect. + // This doesn't seem to be a thing anymore, so we clear the targets list here. + unitList.Clear(); + } + public override void Register() { - OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitSrcAreaEnemy)); OnObjectAreaTargetSelect.Add(new(FilterTargets, 2, Targets.UnitSrcAreaEnemy)); + OnObjectAreaTargetSelect.Add(new(ClearTargets, 3, Targets.UnitSrcAreaEnemy)); + } + } + + [Script] // 316594 - Intimidating Shout (Menace Talent, knock back . root) + class spell_warr_intimidating_shout_menace_knock_back : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.IntimidatingShoutMenaceAoe); + } + + void FilterTargets(List unitList) + { + unitList.Remove(GetExplTargetWorldObject()); + } + + void HandleRoot(uint effIndex) + { + CastSpellExtraArgs args = new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }; + + var caster = GetCaster(); + var targetsGuid = GetHitUnit().GetGUID(); + GetCaster().m_Events.AddEventAtOffset(() => + { + Unit targetUnit = Global.ObjAccessor.GetUnit(caster, targetsGuid); + if (targetUnit != null) + caster.CastSpell(targetUnit, SpellIds.IntimidatingShoutMenaceAoe, args); + }, TimeSpan.FromSeconds(500)); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaEnemy)); + OnEffectHitTarget.Add(new(HandleRoot, 0, SpellEffectName.KnockBack)); + } + } + + [Script] // 385174 - Invigorating Fury (attached to 184364 - Enraged Regeneration) + class spell_warr_invigorating_fury : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.InvigoratingFury, SpellIds.InvigoratingFuryTalent); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.InvigoratingFuryTalent); + } + + void CastHeal() + { + GetCaster().CastSpell(null, SpellIds.InvigoratingFury, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); + } + + public override void Register() + { + AfterCast.Add(new(CastHeal)); } } @@ -435,7 +1028,7 @@ namespace Scripts.Spells.Warrior public override bool Validate(SpellInfo spellInfo) { return ValidateSpellInfo(SpellIds.Stoicism) - && ValidateSpellEffect((spellInfo.Id, 1)); + && ValidateSpellEffect((spellInfo.Id, 1)); } void HandleProc(ProcEventInfo eventInfo) @@ -455,7 +1048,7 @@ namespace Scripts.Spells.Warrior } } - [Script] // 12294 - Mortal Strike 7.1.5 + [Script] // 12294 - Mortal Strike class spell_warr_mortal_strike : SpellScript { public override bool Validate(SpellInfo spellInfo) @@ -463,16 +1056,56 @@ namespace Scripts.Spells.Warrior return ValidateSpellInfo(SpellIds.MortalWounds); } - void HandleDummy(uint effIndex) + void HandleMortalWounds(uint effIndex) { - Unit target = GetHitUnit(); - if (target != null) - GetCaster().CastSpell(target, SpellIds.MortalWounds, true); + GetCaster().CastSpell(GetHitUnit(), SpellIds.MortalWounds, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } public override void Register() { - OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy)); + OnEffectHitTarget.Add(new(HandleMortalWounds, 0, SpellEffectName.SchoolDamage)); + } + } + + // 383854 - Improved Raging Blow (attached to 85288 - Raging Blow, 335097 - Crushing Blow) + [Script] // 392936 - Wrath and Fury (attached to 85288 - Raging Blow, 335097 - Crushing Blow) + class spell_warr_raging_blow_cooldown_reset : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.ImprovedRagingBlow) + && ValidateSpellEffect((SpellIds.WrathAndFury, 0)); + } + + public override bool Load() + { + Unit caster = GetCaster(); + return caster.HasAura(SpellIds.ImprovedRagingBlow) || caster.HasAuraEffect(SpellIds.WrathAndFury, 0); + } + + void HandleResetCooldown(uint effIndex) + { + // it is currently impossible to have Wrath and Fury without having Improved Raging Blow, but we will check it anyway + Unit caster = GetCaster(); + int value = 0; + if (caster.HasAura(SpellIds.ImprovedRagingBlow)) + value = GetEffectValue(); + + AuraEffect auraEffect = caster.GetAuraEffect(SpellIds.WrathAndFury, 0); + if (auraEffect != null) + value += auraEffect.GetAmount(); + + if (RandomHelper.randChance(value)) + caster.GetSpellHistory().RestoreCharge(GetSpellInfo().ChargeCategoryId); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleResetCooldown, 0, SpellEffectName.Dummy)); } } @@ -503,6 +1136,41 @@ namespace Scripts.Spells.Warrior } } + [Script] // 275339 - (attached to 46968 - Shockwave) + class spell_warr_rumbling_earth : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.RumblingEarth, 1)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.RumblingEarth); + } + + void HandleCooldownReduction(uint effIndex) + { + Unit caster = GetCaster(); + Aura rumblingEarth = caster.GetAura(SpellIds.RumblingEarth); + if (rumblingEarth == null) + return; + + AuraEffect minTargetCount = rumblingEarth.GetEffect(0); + AuraEffect cooldownReduction = rumblingEarth.GetEffect(1); + if (minTargetCount == null || cooldownReduction == null) + return; + + if (GetUnitTargetCountForEffect(0) >= minTargetCount.GetAmount()) + GetCaster().GetSpellHistory().ModifyCooldown(GetSpellInfo().Id, TimeSpan.FromSeconds(-cooldownReduction.GetAmount())); + } + + public override void Register() + { + OnEffectHitTarget.Add(new(HandleCooldownReduction, 1, SpellEffectName.ScriptEffect)); + } + } + [Script] // 2565 - Shield Block class spell_warr_shield_block : SpellScript { @@ -544,36 +1212,23 @@ namespace Scripts.Spells.Warrior [Script] // 46968 - Shockwave class spell_warr_shockwave : SpellScript { - uint _targetCount; - public override bool Validate(SpellInfo spellInfo) { - return !ValidateSpellInfo(SpellIds.Shockwave, SpellIds.ShockwaveStun) - && ValidateSpellEffect((spellInfo.Id, 3)); - } - - public override bool Load() - { - return GetCaster().IsPlayer(); + return ValidateSpellInfo(SpellIds.ShockwaveStun); } void HandleStun(uint effIndex) { - GetCaster().CastSpell(GetHitUnit(), SpellIds.ShockwaveStun, true); - ++_targetCount; - } - - // Cooldown reduced by 20 sec if it strikes at least 3 targets. - void HandleAfterCast() - { - if (_targetCount >= (uint)GetEffectInfo(0).CalcValue()) - GetCaster().ToPlayer().GetSpellHistory().ModifyCooldown(GetSpellInfo().Id, TimeSpan.FromSeconds(-GetEffectInfo(3).CalcValue())); + GetCaster().CastSpell(GetHitUnit(), SpellIds.ShockwaveStun, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = GetSpell() + }); } public override void Register() { - OnEffectHitTarget.Add(new(HandleStun, 0, SpellEffectName.Dummy)); - AfterCast.Add(new(HandleAfterCast)); + OnEffectHitTarget.Add(new(HandleStun, 0, SpellEffectName.SchoolDamage)); } } @@ -592,7 +1247,35 @@ namespace Scripts.Spells.Warrior public override void Register() { - OnEffectHitTarget.Add(new(HandleOnHit, 1, SpellEffectName.Dummy)); + OnEffectHitTarget.Add(new(HandleOnHit, 0, SpellEffectName.SchoolDamage)); + } + } + + [Script] // 107570 - Storm Bolt + class spell_warr_storm_bolts : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.StormBolts); + } + + public override bool Load() + { + return !GetCaster().HasAura(SpellIds.StormBolts); + } + + void FilterTargets(List targets) + { + targets.Clear(); + + Unit target = GetExplTargetUnit(); + if (target != null) + targets.Add(target); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy)); } } @@ -624,25 +1307,40 @@ namespace Scripts.Spells.Warrior } } - [Script] // 52437 - Sudden Death + [Script] // 280776 - Sudden Death class spell_warr_sudden_death : AuraScript { - public override bool Validate(SpellInfo spellInfo) + static bool CheckProc(ProcEventInfo eventInfo) { - return ValidateSpellInfo(SpellIds.ColossusSmash); - } - - void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) - { - // Remove cooldown on Colossus Smash - Player player = GetTarget().ToPlayer(); - if (player != null) - player.GetSpellHistory().ResetCooldown(SpellIds.ColossusSmash, true); + // should only proc on primary target + return eventInfo.GetActionTarget() == eventInfo.GetProcSpell().m_targets.GetUnitTarget(); } public override void Register() { - AfterEffectApply.Add(new(HandleApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); // correct? + DoCheckProc.Add(new(CheckProc)); + } + } + + [Script] // 280721 - Sudden Death + class spell_warr_sudden_death_proc : AuraScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.SuddenDeathBuff); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + GetTarget().CastSpell(null, SpellIds.SuddenDeathBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError + }); + } + + public override void Register() + { + OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy)); } } @@ -690,6 +1388,73 @@ namespace Scripts.Spells.Warrior } } + [Script] // 388933 - Tenderize + class spell_warr_tenderize : AuraScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Enrage, SpellIds.SlaughteringStrikesBuff, SpellIds.SlaughteringStrikes); + } + + void HandleProc(ProcEventInfo eventInfo) + { + GetTarget().CastSpell(null, SpellIds.Enrage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = eventInfo.GetProcSpell() + }); + } + + void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + Unit target = GetTarget(); + if (!target.HasAura(SpellIds.SlaughteringStrikes)) + return; + + target.CastSpell(null, SpellIds.SlaughteringStrikesBuff, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = eventInfo.GetProcSpell(), + SpellValueOverrides = { new(SpellValueMod.AuraStack, aurEff.GetAmount()) } + }); + } + + public override void Register() + { + OnProc.Add(new(HandleProc)); + OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy)); + } + } + + [Script] // 394329 - Titanic Rage + class spell_warr_titanic_rage : AuraScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.WhirlwindCleaveAura); + } + + void HandleProc(ProcEventInfo eventInfo) + { + Player target = GetTarget().ToPlayer(); + if (target == null) + return; + + target.CastSpell(null, SpellIds.Enrage, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError, + TriggeringSpell = eventInfo.GetProcSpell() + }); + + WarriorMisc.ApplyWhirlwindCleaveAura(target, GetCastDifficulty(), null); + } + + public override void Register() + { + OnProc.Add(new(HandleProc)); + } + } + [Script] // 215538 - Trauma class spell_warr_trauma : AuraScript { @@ -702,7 +1467,7 @@ namespace Scripts.Spells.Warrior { Unit target = eventInfo.GetActionTarget(); //Get 25% of damage from the spell casted (Slam & Whirlwind) plus Remaining Damage from Aura - int damage = (int)(MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), aurEff.GetAmount()) / SpellMgr.GetSpellInfo(SpellIds.TraumaEffect, GetCastDifficulty()).GetMaxTicks()); + int damage = (int)(MathFunctions.CalculatePct(eventInfo.GetDamageInfo().GetDamage(), aurEff.GetAmount()) / Global.SpellMgr.GetSpellInfo(SpellIds.TraumaEffect, GetCastDifficulty()).GetMaxTicks()); CastSpellExtraArgs args = new(TriggerCastFlags.FullMask); args.AddSpellMod(SpellValueMod.BasePoint0, damage); GetCaster().CastSpell(target, SpellIds.TraumaEffect, args); @@ -736,6 +1501,70 @@ namespace Scripts.Spells.Warrior } } + [Script] // 389603 - Unbridled Ferocity + class spell_warr_unbridled_ferocity : AuraScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.Recklessness) + && ValidateSpellEffect((spellInfo.Id, 1)) + && spellInfo.GetEffect(0).IsAura(AuraType.Dummy) + && spellInfo.GetEffect(1).IsAura(AuraType.Dummy); + } + + void HandleProc(ProcEventInfo eventInfo) + { + int durationMs = GetEffect(1).GetAmount(); + + GetTarget().CastSpell(null, SpellIds.Recklessness, new CastSpellExtraArgs() + { + TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError | TriggerCastFlags.IgnoreSpellAndCategoryCD, + SpellValueOverrides = { new(SpellValueMod.Duration, durationMs) } + }); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return RandomHelper.randChance(GetEffect(0).GetAmount()); + } + + public override void Register() + { + DoCheckProc.Add(new(CheckProc)); + OnProc.Add(new(HandleProc)); + } + } + + // 383885 - Vicious Contempt (attached to 23881 - Bloodthirst) + [Script] // 383885 - Vicious Contempt (attached to 335096 - Bloodbath) + class spell_warr_vicious_contempt : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellEffect((SpellIds.ViciousContempt, 0)); + } + + public override bool Load() + { + return GetCaster().HasAura(SpellIds.ViciousContempt); + } + + void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod) + { + if (!victim.HasAuraState(AuraStateType.Wounded35Percent)) + return; + + AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.ViciousContempt, 0); + if (aurEff != null) + MathFunctions.AddPct(ref pctMod, aurEff.GetAmount()); + } + + public override void Register() + { + CalcDamage.Add(new(CalculateDamage)); + } + } + [Script] // 32215 - Victorious State class spell_warr_victorious_state : AuraScript {