diff --git a/data/sql/updates/pending_db_world/rev_1597581112860069800.sql b/data/sql/updates/pending_db_world/rev_1597581112860069800.sql new file mode 100644 index 000000000..a597852c6 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1597581112860069800.sql @@ -0,0 +1,5 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1597581112860069800'); + +-- Nightfall +UPDATE `item_template` SET `spellppmRate_1`=2.5, `ScriptName`='item_generic_limit_chance_above_60' WHERE `entry`=19169; + diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 96c6ed5ab..6e5062036 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8564,7 +8564,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 chance = GetWeaponProcChance(); } - if (roll_chance_f(chance)) + if (roll_chance_f(chance) && sScriptMgr->OnCastItemCombatSpell(this, target, spellInfo, item)) CastSpell(target, spellInfo->Id, TriggerCastFlags(TRIGGERED_FULL_MASK&~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), item); } } diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index bef6946a0..e71cda5e3 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -722,6 +722,17 @@ bool ScriptMgr::OnItemRemove(Player * player, Item * item) } +bool ScriptMgr::OnCastItemCombatSpell(Player* player, Unit* victim, SpellInfo const* spellInfo, Item* item) +{ + ASSERT(player); + ASSERT(victim); + ASSERT(spellInfo); + ASSERT(item); + + GET_SCRIPT_RET(ItemScript, item->GetScriptId(), tmpscript, true); + return tmpscript->OnCastItemCombatSpell(player, victim, spellInfo, item); +} + void ScriptMgr::OnGossipSelect(Player* player, Item* item, uint32 sender, uint32 action) { ASSERT(player); diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index ffcaa8633..f4e4973d9 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -47,6 +47,7 @@ class Quest; class ScriptMgr; class Spell; class SpellScript; +class SpellInfo; class SpellCastTargets; class Transport; class StaticTransport; @@ -425,6 +426,9 @@ class ItemScript : public ScriptObject // Called when the item is destroyed. 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) + virtual bool OnCastItemCombatSpell(Player* /*player*/, Unit* /*victim*/, SpellInfo const* /*spellInfo*/, Item* /*item*/) { return true; } + // Called when the item expires (is destroyed). virtual bool OnExpire(Player* /*player*/, ItemTemplate const* /*proto*/) { return false; } @@ -1304,6 +1308,7 @@ class ScriptMgr bool OnItemUse(Player* player, Item* item, SpellCastTargets const& targets); bool OnItemExpire(Player* player, ItemTemplate const* proto); bool OnItemRemove(Player* player, Item* item); + bool OnCastItemCombatSpell(Player* player, Unit* victim, SpellInfo const* spellInfo, Item* item); void OnGossipSelect(Player* player, Item* item, uint32 sender, uint32 action); void OnGossipSelectCode(Player* player, Item* item, uint32 sender, uint32 action, const char* code); diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp index ba1809f3d..328c894e2 100644 --- a/src/server/scripts/World/item_scripts.cpp +++ b/src/server/scripts/World/item_scripts.cpp @@ -234,6 +234,30 @@ public: } }; +// Only used currently for +// 19169: Nightfall +class item_generic_limit_chance_above_60 : public ItemScript +{ +public: + item_generic_limit_chance_above_60() : ItemScript("item_generic_limit_chance_above_60") { } + + bool OnCastItemCombatSpell(Player* /*player*/, Unit* victim, SpellInfo const* /*spellInfo*/, Item* /*item*/) override + { + // spell proc chance gets severely reduced on victims > 60 (formula unknown) + if (victim->getLevel() > 60) + { + // gives ~0.1% proc chance at lvl 70 + float const lvlPenaltyFactor = 9.93f; + float const failureChance = (victim->getLevel() - 60) * lvlPenaltyFactor; + + // base ppm chance was already rolled, only roll success chance + return !roll_chance_f(failureChance); + } + + return true; + } +}; + void AddSC_item_scripts() { new item_only_for_flight(); @@ -244,4 +268,5 @@ void AddSC_item_scripts() new item_disgusting_jar(); new item_petrov_cluster_bombs(); new item_captured_frog(); + new item_generic_limit_chance_above_60(); }