diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index 9fd021d81..2aa47e5fb 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -3304,7 +3304,7 @@ namespace Game.Entities else if (chance > 100.0f) chance = GetWeaponProcChance(); - if (RandomHelper.randChance(chance)) + if (RandomHelper.randChance(chance) && Global.ScriptMgr.OnCastItemCombatSpell(this, damageInfo.GetVictim(), spellInfo, item)) CastSpell(damageInfo.GetVictim(), spellInfo.Id, true, item); } } diff --git a/Source/Game/Scripting/CoreScripts.cs b/Source/Game/Scripting/CoreScripts.cs index e8af146fe..8e24d134d 100644 --- a/Source/Game/Scripting/CoreScripts.cs +++ b/Source/Game/Scripting/CoreScripts.cs @@ -279,6 +279,12 @@ namespace Game.Scripting // Called when the item expires (is destroyed). public virtual bool OnExpire(Player player, ItemTemplate proto) { return false; } + + // Called when the item is destroyed. + public virtual bool OnRemove(Player player, Item item) { return false; } + + // Called before casting a combat spell from this item (chance on hit spells of item template, can be used to prevent cast if returning false) + public virtual bool OnCastItemCombatSpell(Player player, Unit victim, SpellInfo spellInfo, Item item) { return true; } } public class UnitScript : ScriptObject diff --git a/Source/Game/Scripting/ScriptManager.cs b/Source/Game/Scripting/ScriptManager.cs index c46ae9b7e..0c5d416c4 100644 --- a/Source/Game/Scripting/ScriptManager.cs +++ b/Source/Game/Scripting/ScriptManager.cs @@ -738,6 +738,22 @@ namespace Game.Scripting return RunScriptRet(p => p.OnExpire(player, proto), proto.ScriptId); } + public bool OnItemRemove(Player player, Item item) + { + Cypher.Assert(player != null); + Cypher.Assert(item != null); + + return RunScriptRet(tmpscript => tmpscript.OnRemove(player, item), item.GetScriptId()); + } + public bool OnCastItemCombatSpell(Player player, Unit victim, SpellInfo spellInfo, Item item) + { + Cypher.Assert(player != null); + Cypher.Assert(victim != null); + Cypher.Assert(spellInfo != null); + Cypher.Assert(item != null); + + return RunScriptRet(tmpscript => tmpscript.OnCastItemCombatSpell(player, victim, spellInfo, item), item.GetScriptId()); + } //CreatureScript public bool OnDummyEffect(Unit caster, uint spellId, uint effIndex, Creature target) diff --git a/Source/Scripts/World/ItemScripts.cs b/Source/Scripts/World/ItemScripts.cs index 93dbcbf2a..ec0b3eea3 100644 --- a/Source/Scripts/World/ItemScripts.cs +++ b/Source/Scripts/World/ItemScripts.cs @@ -360,4 +360,27 @@ namespace Scripts.World return true; } } + + // Only used currently for + [Script]// 19169: Nightfall + class item_generic_limit_chance_above_60 : ItemScript + { + public item_generic_limit_chance_above_60() : base("item_generic_limit_chance_above_60") { } + + public override bool OnCastItemCombatSpell(Player player, Unit victim, SpellInfo spellInfo, Item item) + { + // spell proc chance gets severely reduced on victims > 60 (formula unknown) + if (victim.getLevel() > 60) + { + // gives ~0.1% proc chance at lvl 70 + float lvlPenaltyFactor = 9.93f; + float failureChance = (victim.GetLevelForTarget(player) - 60) * lvlPenaltyFactor; + + // base ppm chance was already rolled, only roll success chance + return !RandomHelper.randChance(failureChance); + } + + return true; + } + } }