/src/server/scripts/Spells/spell_rogue.cpp

https://gitlab.com/tkrokli/TrinityCore_434 · C++ · 1031 lines · 806 code · 171 blank · 54 comment · 86 complexity · a51cc85015ef6d6673480701c500bdb8 MD5 · raw file

  1. /*
  2. * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /*
  18. * Scripts for spells with SPELLFAMILY_ROGUE and SPELLFAMILY_GENERIC spells used by rogue players.
  19. * Ordered alphabetically using scriptname.
  20. * Scriptnames of files in this file should be prefixed with "spell_rog_".
  21. */
  22. #include "Player.h"
  23. #include "ScriptMgr.h"
  24. #include "SpellScript.h"
  25. #include "SpellAuraEffects.h"
  26. #include "SpellHistory.h"
  27. #include "Containers.h"
  28. enum RogueSpells
  29. {
  30. SPELL_ROGUE_BLADE_FLURRY = 13877,
  31. SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK = 22482,
  32. SPELL_ROGUE_CHEAT_DEATH_COOLDOWN = 31231,
  33. SPELL_ROGUE_CRIPPLING_POISON = 3409,
  34. SPELL_ROGUE_GLYPH_OF_PREPARATION = 56819,
  35. SPELL_ROGUE_KILLING_SPREE = 51690,
  36. SPELL_ROGUE_KILLING_SPREE_TELEPORT = 57840,
  37. SPELL_ROGUE_KILLING_SPREE_WEAPON_DMG = 57841,
  38. SPELL_ROGUE_KILLING_SPREE_DMG_BUFF = 61851,
  39. SPELL_ROGUE_MASTER_OF_SUBTLETY_DAMAGE_PERCENT = 31665,
  40. SPELL_ROGUE_MASTER_OF_SUBTLETY_PASSIVE = 31223,
  41. SPELL_ROGUE_MASTER_OF_SUBTLETY_PERIODIC = 31666,
  42. SPELL_ROGUE_OVERKILL_TALENT = 58426,
  43. SPELL_ROGUE_OVERKILL_PERIODIC = 58428,
  44. SPELL_ROGUE_OVERKILL_POWER_REGEN = 58427,
  45. SPELL_ROGUE_PREY_ON_THE_WEAK = 58670,
  46. SPELL_ROGUE_SHIV_TRIGGERED = 5940,
  47. SPELL_ROGUE_SILCE_AND_DICE = 5171,
  48. SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST = 57933,
  49. SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628,
  50. SPELL_ROGUE_SERRATED_BLADES_R1 = 14171,
  51. SPELL_ROGUE_RUPTURE = 1943,
  52. };
  53. enum RogueSpellIcons
  54. {
  55. ICON_ROGUE_IMPROVED_RECUPERATE = 4819
  56. };
  57. // 13877, 33735, (check 51211, 65956) - Blade Flurry
  58. class spell_rog_blade_flurry : public SpellScriptLoader
  59. {
  60. public:
  61. spell_rog_blade_flurry() : SpellScriptLoader("spell_rog_blade_flurry") { }
  62. class spell_rog_blade_flurry_AuraScript : public AuraScript
  63. {
  64. PrepareAuraScript(spell_rog_blade_flurry_AuraScript);
  65. public:
  66. spell_rog_blade_flurry_AuraScript()
  67. {
  68. _procTarget = nullptr;
  69. }
  70. private:
  71. bool Validate(SpellInfo const* /*spellInfo*/) override
  72. {
  73. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK))
  74. return false;
  75. return true;
  76. }
  77. bool CheckProc(ProcEventInfo& eventInfo)
  78. {
  79. _procTarget = GetTarget()->SelectNearbyTarget(eventInfo.GetProcTarget());
  80. return _procTarget && eventInfo.GetDamageInfo();
  81. }
  82. void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
  83. {
  84. PreventDefaultAction();
  85. TC_LOG_ERROR("misc", "damage: %u procSpell: %u",
  86. eventInfo.GetDamageInfo()->GetDamage(), eventInfo.GetDamageInfo()->GetSpellInfo() ? eventInfo.GetDamageInfo()->GetSpellInfo()->Id : 0);
  87. GetTarget()->CastCustomSpell(SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK, SPELLVALUE_BASE_POINT0, eventInfo.GetDamageInfo()->GetDamage(), _procTarget, true, NULL, aurEff);
  88. }
  89. void Register() override
  90. {
  91. DoCheckProc += AuraCheckProcFn(spell_rog_blade_flurry_AuraScript::CheckProc);
  92. if (m_scriptSpellId == SPELL_ROGUE_BLADE_FLURRY)
  93. OnEffectProc += AuraEffectProcFn(spell_rog_blade_flurry_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_MOD_POWER_REGEN_PERCENT);
  94. else
  95. OnEffectProc += AuraEffectProcFn(spell_rog_blade_flurry_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_MOD_MELEE_HASTE);
  96. }
  97. private:
  98. Unit* _procTarget;
  99. };
  100. AuraScript* GetAuraScript() const override
  101. {
  102. return new spell_rog_blade_flurry_AuraScript();
  103. }
  104. };
  105. // 31228 - Cheat Death
  106. class spell_rog_cheat_death : public SpellScriptLoader
  107. {
  108. public:
  109. spell_rog_cheat_death() : SpellScriptLoader("spell_rog_cheat_death") { }
  110. class spell_rog_cheat_death_AuraScript : public AuraScript
  111. {
  112. PrepareAuraScript(spell_rog_cheat_death_AuraScript);
  113. public:
  114. spell_rog_cheat_death_AuraScript()
  115. {
  116. absorbChance = 0;
  117. }
  118. private:
  119. uint32 absorbChance;
  120. bool Validate(SpellInfo const* /*spellInfo*/) override
  121. {
  122. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_CHEAT_DEATH_COOLDOWN))
  123. return false;
  124. return true;
  125. }
  126. bool Load() override
  127. {
  128. absorbChance = GetSpellInfo()->Effects[EFFECT_0].CalcValue();
  129. return GetUnitOwner()->GetTypeId() == TYPEID_PLAYER;
  130. }
  131. void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
  132. {
  133. // Set absorbtion amount to unlimited
  134. amount = -1;
  135. }
  136. void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
  137. {
  138. Player* target = GetTarget()->ToPlayer();
  139. if (dmgInfo.GetDamage() < target->GetHealth() || target->GetSpellHistory()->HasCooldown(SPELL_ROGUE_CHEAT_DEATH_COOLDOWN) || !roll_chance_i(absorbChance))
  140. return;
  141. target->CastSpell(target, SPELL_ROGUE_CHEAT_DEATH_COOLDOWN, true);
  142. target->GetSpellHistory()->AddCooldown(SPELL_ROGUE_CHEAT_DEATH_COOLDOWN, 0, std::chrono::minutes(1));
  143. uint32 health10 = target->CountPctFromMaxHealth(10);
  144. // hp > 10% - absorb hp till 10%
  145. if (target->GetHealth() > health10)
  146. absorbAmount = dmgInfo.GetDamage() - target->GetHealth() + health10;
  147. // hp lower than 10% - absorb everything
  148. else
  149. absorbAmount = dmgInfo.GetDamage();
  150. }
  151. void Register() override
  152. {
  153. DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_cheat_death_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
  154. OnEffectAbsorb += AuraEffectAbsorbFn(spell_rog_cheat_death_AuraScript::Absorb, EFFECT_0);
  155. }
  156. };
  157. AuraScript* GetAuraScript() const override
  158. {
  159. return new spell_rog_cheat_death_AuraScript();
  160. }
  161. };
  162. // -51625 - Deadly Brew
  163. class spell_rog_crippling_poison : public SpellScriptLoader
  164. {
  165. public:
  166. spell_rog_crippling_poison() : SpellScriptLoader("spell_rog_crippling_poison") { }
  167. class spell_rog_crippling_poison_AuraScript : public AuraScript
  168. {
  169. PrepareAuraScript(spell_rog_crippling_poison_AuraScript);
  170. bool Validate(SpellInfo const* /*spellInfo*/) override
  171. {
  172. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_CRIPPLING_POISON))
  173. return false;
  174. return true;
  175. }
  176. void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
  177. {
  178. PreventDefaultAction();
  179. GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_ROGUE_CRIPPLING_POISON, true, NULL, aurEff);
  180. }
  181. void Register() override
  182. {
  183. OnEffectProc += AuraEffectProcFn(spell_rog_crippling_poison_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY);
  184. }
  185. };
  186. AuraScript* GetAuraScript() const override
  187. {
  188. return new spell_rog_crippling_poison_AuraScript();
  189. }
  190. };
  191. // -51664 - Cut to the Chase
  192. class spell_rog_cut_to_the_chase : public SpellScriptLoader
  193. {
  194. public:
  195. spell_rog_cut_to_the_chase () : SpellScriptLoader("spell_rog_cut_to_the_chase") { }
  196. class spell_rog_cut_to_the_chase_AuraScript : public AuraScript
  197. {
  198. PrepareAuraScript(spell_rog_cut_to_the_chase_AuraScript);
  199. void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
  200. {
  201. PreventDefaultAction();
  202. if (Aura* aur = GetTarget()->GetAura(SPELL_ROGUE_SILCE_AND_DICE))
  203. aur->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true);
  204. }
  205. void Register() override
  206. {
  207. OnEffectProc += AuraEffectProcFn(spell_rog_cut_to_the_chase_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
  208. }
  209. };
  210. AuraScript* GetAuraScript() const override
  211. {
  212. return new spell_rog_cut_to_the_chase_AuraScript();
  213. }
  214. };
  215. // 2818 - Deadly Poison
  216. class spell_rog_deadly_poison : public SpellScriptLoader
  217. {
  218. public:
  219. spell_rog_deadly_poison() : SpellScriptLoader("spell_rog_deadly_poison") { }
  220. class spell_rog_deadly_poison_SpellScript : public SpellScript
  221. {
  222. PrepareSpellScript(spell_rog_deadly_poison_SpellScript);
  223. public:
  224. spell_rog_deadly_poison_SpellScript()
  225. {
  226. _stackAmount = 0;
  227. }
  228. private:
  229. bool Load() override
  230. {
  231. // at this point CastItem must already be initialized
  232. return GetCaster()->GetTypeId() == TYPEID_PLAYER && GetCastItem();
  233. }
  234. void HandleBeforeHit()
  235. {
  236. if (Unit* target = GetHitUnit())
  237. // Deadly Poison
  238. if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x10000, 0x80000, 0, GetCaster()->GetGUID()))
  239. _stackAmount = aurEff->GetBase()->GetStackAmount();
  240. }
  241. void HandleAfterHit()
  242. {
  243. if (_stackAmount < 5)
  244. return;
  245. Player* player = GetCaster()->ToPlayer();
  246. if (Unit* target = GetHitUnit())
  247. {
  248. Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
  249. if (item == GetCastItem())
  250. item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
  251. if (!item)
  252. return;
  253. // item combat enchantments
  254. for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
  255. {
  256. if (slot > PRISMATIC_ENCHANTMENT_SLOT && slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
  257. continue;
  258. SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot)));
  259. if (!enchant)
  260. continue;
  261. for (uint8 s = 0; s < 3; ++s)
  262. {
  263. if (enchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
  264. continue;
  265. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(enchant->spellid[s]);
  266. if (!spellInfo)
  267. {
  268. TC_LOG_ERROR("spells", "Player::CastItemCombatSpell Enchant %i, player (Name: %s, GUID: %u) cast unknown spell %i", enchant->ID, player->GetName().c_str(), player->GetGUIDLow(), enchant->spellid[s]);
  269. continue;
  270. }
  271. // Proc only rogue poisons
  272. if (spellInfo->SpellFamilyName != SPELLFAMILY_ROGUE || spellInfo->Dispel != DISPEL_POISON)
  273. continue;
  274. // Do not reproc deadly
  275. if (spellInfo->SpellFamilyFlags.IsEqual(0x10000, 0x80000, 0))
  276. continue;
  277. if (spellInfo->IsPositive())
  278. player->CastSpell(player, enchant->spellid[s], true, item);
  279. else
  280. player->CastSpell(target, enchant->spellid[s], true, item);
  281. }
  282. }
  283. }
  284. }
  285. void Register() override
  286. {
  287. BeforeHit += SpellHitFn(spell_rog_deadly_poison_SpellScript::HandleBeforeHit);
  288. AfterHit += SpellHitFn(spell_rog_deadly_poison_SpellScript::HandleAfterHit);
  289. }
  290. uint8 _stackAmount;
  291. };
  292. SpellScript* GetSpellScript() const override
  293. {
  294. return new spell_rog_deadly_poison_SpellScript();
  295. }
  296. };
  297. // 51690 - Killing Spree
  298. #define KillingSpreeScriptName "spell_rog_killing_spree"
  299. class spell_rog_killing_spree : public SpellScriptLoader
  300. {
  301. public:
  302. spell_rog_killing_spree() : SpellScriptLoader(KillingSpreeScriptName) { }
  303. class spell_rog_killing_spree_SpellScript : public SpellScript
  304. {
  305. PrepareSpellScript(spell_rog_killing_spree_SpellScript);
  306. void FilterTargets(std::list<WorldObject*>& targets)
  307. {
  308. if (targets.empty() || GetCaster()->GetVehicleBase())
  309. FinishCast(SPELL_FAILED_OUT_OF_RANGE);
  310. }
  311. void HandleDummy(SpellEffIndex /*effIndex*/)
  312. {
  313. if (Aura* aura = GetCaster()->GetAura(SPELL_ROGUE_KILLING_SPREE))
  314. {
  315. if (spell_rog_killing_spree_AuraScript* script = dynamic_cast<spell_rog_killing_spree_AuraScript*>(aura->GetScriptByName(KillingSpreeScriptName)))
  316. script->AddTarget(GetHitUnit());
  317. }
  318. }
  319. void Register() override
  320. {
  321. OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rog_killing_spree_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
  322. OnEffectHitTarget += SpellEffectFn(spell_rog_killing_spree_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
  323. }
  324. };
  325. SpellScript* GetSpellScript() const override
  326. {
  327. return new spell_rog_killing_spree_SpellScript();
  328. }
  329. class spell_rog_killing_spree_AuraScript : public AuraScript
  330. {
  331. PrepareAuraScript(spell_rog_killing_spree_AuraScript);
  332. bool Validate(SpellInfo const* /*spellInfo*/) override
  333. {
  334. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_KILLING_SPREE_TELEPORT)
  335. || !sSpellMgr->GetSpellInfo(SPELL_ROGUE_KILLING_SPREE_WEAPON_DMG)
  336. || !sSpellMgr->GetSpellInfo(SPELL_ROGUE_KILLING_SPREE_DMG_BUFF))
  337. return false;
  338. return true;
  339. }
  340. void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
  341. {
  342. GetTarget()->CastSpell(GetTarget(), SPELL_ROGUE_KILLING_SPREE_DMG_BUFF, true);
  343. }
  344. void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
  345. {
  346. while (!_targets.empty())
  347. {
  348. ObjectGuid guid = Trinity::Containers::SelectRandomContainerElement(_targets);
  349. if (Unit* target = ObjectAccessor::GetUnit(*GetTarget(), guid))
  350. {
  351. GetTarget()->CastSpell(target, SPELL_ROGUE_KILLING_SPREE_TELEPORT, true);
  352. GetTarget()->CastSpell(target, SPELL_ROGUE_KILLING_SPREE_WEAPON_DMG, true);
  353. break;
  354. }
  355. else
  356. _targets.remove(guid);
  357. }
  358. }
  359. void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
  360. {
  361. GetTarget()->RemoveAurasDueToSpell(SPELL_ROGUE_KILLING_SPREE_DMG_BUFF);
  362. }
  363. void Register() override
  364. {
  365. AfterEffectApply += AuraEffectApplyFn(spell_rog_killing_spree_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
  366. OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_killing_spree_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
  367. AfterEffectRemove += AuraEffectRemoveFn(spell_rog_killing_spree_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
  368. }
  369. public:
  370. void AddTarget(Unit* target)
  371. {
  372. _targets.push_back(target->GetGUID());
  373. }
  374. private:
  375. GuidList _targets;
  376. };
  377. AuraScript* GetAuraScript() const override
  378. {
  379. return new spell_rog_killing_spree_AuraScript();
  380. }
  381. };
  382. // 31666 - Master of Subtlety
  383. class spell_rog_master_of_subtlety : public SpellScriptLoader
  384. {
  385. public:
  386. spell_rog_master_of_subtlety() : SpellScriptLoader("spell_rog_master_of_subtlety") { }
  387. class spell_rog_master_of_subtlety_AuraScript : public AuraScript
  388. {
  389. PrepareAuraScript(spell_rog_master_of_subtlety_AuraScript);
  390. bool Validate(SpellInfo const* /*spellInfo*/)
  391. {
  392. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_MASTER_OF_SUBTLETY_DAMAGE_PERCENT))
  393. return false;
  394. return true;
  395. }
  396. void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
  397. {
  398. Unit* target = GetTarget();
  399. if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
  400. target->RemoveAurasDueToSpell(SPELL_ROGUE_MASTER_OF_SUBTLETY_DAMAGE_PERCENT);
  401. }
  402. void Register()
  403. {
  404. OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_master_of_subtlety_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
  405. }
  406. };
  407. AuraScript* GetAuraScript() const
  408. {
  409. return new spell_rog_master_of_subtlety_AuraScript();
  410. }
  411. };
  412. // 31130 - Nerves of Steel
  413. class spell_rog_nerves_of_steel : public SpellScriptLoader
  414. {
  415. public:
  416. spell_rog_nerves_of_steel() : SpellScriptLoader("spell_rog_nerves_of_steel") { }
  417. class spell_rog_nerves_of_steel_AuraScript : public AuraScript
  418. {
  419. PrepareAuraScript(spell_rog_nerves_of_steel_AuraScript);
  420. public:
  421. spell_rog_nerves_of_steel_AuraScript()
  422. {
  423. absorbPct = 0;
  424. }
  425. private:
  426. uint32 absorbPct;
  427. bool Load() override
  428. {
  429. absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster());
  430. return true;
  431. }
  432. void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
  433. {
  434. // Set absorbtion amount to unlimited
  435. amount = -1;
  436. }
  437. void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
  438. {
  439. // reduces all damage taken while stun or fear
  440. if (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_FLEEING) || (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1<<MECHANIC_STUN)))
  441. absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct);
  442. }
  443. void Register() override
  444. {
  445. DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_nerves_of_steel_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
  446. OnEffectAbsorb += AuraEffectAbsorbFn(spell_rog_nerves_of_steel_AuraScript::Absorb, EFFECT_0);
  447. }
  448. };
  449. AuraScript* GetAuraScript() const override
  450. {
  451. return new spell_rog_nerves_of_steel_AuraScript();
  452. }
  453. };
  454. // 58428 - Overkill
  455. class spell_rog_overkill : public SpellScriptLoader
  456. {
  457. public:
  458. spell_rog_overkill() : SpellScriptLoader("spell_rog_overkill") { }
  459. class spell_rog_overkill_AuraScript : public AuraScript
  460. {
  461. PrepareAuraScript(spell_rog_overkill_AuraScript);
  462. bool Validate(SpellInfo const* /*spellInfo*/)
  463. {
  464. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_OVERKILL_POWER_REGEN))
  465. return false;
  466. return true;
  467. }
  468. void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
  469. {
  470. Unit* target = GetTarget();
  471. if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
  472. target->RemoveAurasDueToSpell(SPELL_ROGUE_OVERKILL_POWER_REGEN);
  473. }
  474. void Register()
  475. {
  476. OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_overkill_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
  477. }
  478. };
  479. AuraScript* GetAuraScript() const
  480. {
  481. return new spell_rog_overkill_AuraScript();
  482. }
  483. };
  484. // 14185 - Preparation
  485. class spell_rog_preparation : public SpellScriptLoader
  486. {
  487. public:
  488. spell_rog_preparation() : SpellScriptLoader("spell_rog_preparation") { }
  489. class spell_rog_preparation_SpellScript : public SpellScript
  490. {
  491. PrepareSpellScript(spell_rog_preparation_SpellScript);
  492. bool Load() override
  493. {
  494. return GetCaster()->GetTypeId() == TYPEID_PLAYER;
  495. }
  496. bool Validate(SpellInfo const* /*spellInfo*/) override
  497. {
  498. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_GLYPH_OF_PREPARATION))
  499. return false;
  500. return true;
  501. }
  502. void HandleDummy(SpellEffIndex /*effIndex*/)
  503. {
  504. Unit* caster = GetCaster();
  505. caster->GetSpellHistory()->ResetCooldowns([caster](SpellHistory::CooldownStorageType::iterator itr) -> bool
  506. {
  507. SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
  508. if (spellInfo->SpellFamilyName != SPELLFAMILY_ROGUE)
  509. return false;
  510. return (spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG0_ROGUE_VAN_SPRINT) || // Vanish, Sprint
  511. // Glyph of Preparation
  512. (caster->HasAura(SPELL_ROGUE_GLYPH_OF_PREPARATION) &&
  513. (spellInfo->SpellFamilyFlags[1] & SPELLFAMILYFLAG1_ROGUE_DISMANTLE_SMOKE_BOMB || // Dismantle, Smoke Bomb
  514. spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG0_ROGUE_KICK));
  515. }, true);
  516. }
  517. void Register() override
  518. {
  519. OnEffectHitTarget += SpellEffectFn(spell_rog_preparation_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
  520. }
  521. };
  522. SpellScript* GetSpellScript() const override
  523. {
  524. return new spell_rog_preparation_SpellScript();
  525. }
  526. };
  527. // 51685 - Prey on the Weak
  528. class spell_rog_prey_on_the_weak : public SpellScriptLoader
  529. {
  530. public:
  531. spell_rog_prey_on_the_weak() : SpellScriptLoader("spell_rog_prey_on_the_weak") { }
  532. class spell_rog_prey_on_the_weak_AuraScript : public AuraScript
  533. {
  534. PrepareAuraScript(spell_rog_prey_on_the_weak_AuraScript);
  535. bool Validate(SpellInfo const* /*spellInfo*/) override
  536. {
  537. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_PREY_ON_THE_WEAK))
  538. return false;
  539. return true;
  540. }
  541. void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
  542. {
  543. Unit* target = GetTarget();
  544. Unit* victim = target->GetVictim();
  545. if (victim && (target->GetHealthPct() > victim->GetHealthPct()))
  546. {
  547. if (!target->HasAura(SPELL_ROGUE_PREY_ON_THE_WEAK))
  548. {
  549. int32 bp = GetSpellInfo()->Effects[EFFECT_0].CalcValue();
  550. target->CastCustomSpell(target, SPELL_ROGUE_PREY_ON_THE_WEAK, &bp, nullptr, nullptr, true);
  551. }
  552. }
  553. else
  554. target->RemoveAurasDueToSpell(SPELL_ROGUE_PREY_ON_THE_WEAK);
  555. }
  556. void Register() override
  557. {
  558. OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_prey_on_the_weak_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
  559. }
  560. };
  561. AuraScript* GetAuraScript() const override
  562. {
  563. return new spell_rog_prey_on_the_weak_AuraScript();
  564. }
  565. };
  566. // 73651 - Recuperate
  567. class spell_rog_recuperate : public SpellScriptLoader
  568. {
  569. public:
  570. spell_rog_recuperate() : SpellScriptLoader("spell_rog_recuperate") { }
  571. class spell_rog_recuperate_AuraScript : public AuraScript
  572. {
  573. PrepareAuraScript(spell_rog_recuperate_AuraScript);
  574. bool Load() override
  575. {
  576. return GetCaster()->GetTypeId() == TYPEID_PLAYER;
  577. }
  578. void OnPeriodic(AuraEffect const* /*aurEff*/)
  579. {
  580. if (Unit* caster = GetCaster())
  581. if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_0))
  582. effect->RecalculateAmount(caster);
  583. }
  584. void CalculateBonus(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
  585. {
  586. canBeRecalculated = false;
  587. if (Unit* caster = GetCaster())
  588. {
  589. int32 baseAmount = GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster) * 1000;
  590. // Improved Recuperate
  591. if (AuraEffect const* auraEffect = caster->GetDummyAuraEffect(SPELLFAMILY_ROGUE, ICON_ROGUE_IMPROVED_RECUPERATE, EFFECT_0))
  592. baseAmount += auraEffect->GetAmount();
  593. amount = CalculatePct(caster->GetMaxHealth(), float(baseAmount) / 1000.0f);
  594. }
  595. }
  596. void Register() override
  597. {
  598. OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_recuperate_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
  599. DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_recuperate_AuraScript::CalculateBonus, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
  600. }
  601. };
  602. AuraScript* GetAuraScript() const override
  603. {
  604. return new spell_rog_recuperate_AuraScript();
  605. }
  606. };
  607. // 1943 - Rupture
  608. class spell_rog_rupture : public SpellScriptLoader
  609. {
  610. public:
  611. spell_rog_rupture() : SpellScriptLoader("spell_rog_rupture") { }
  612. class spell_rog_rupture_AuraScript : public AuraScript
  613. {
  614. PrepareAuraScript(spell_rog_rupture_AuraScript);
  615. bool Load() override
  616. {
  617. Unit* caster = GetCaster();
  618. return caster && caster->GetTypeId() == TYPEID_PLAYER;
  619. }
  620. void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
  621. {
  622. if (Unit* caster = GetCaster())
  623. {
  624. canBeRecalculated = false;
  625. float const attackpowerPerCombo[6] =
  626. {
  627. 0.0f,
  628. 0.015f, // 1 point: ${($m1 + $b1*1 + 0.015 * $AP) * 4} damage over 8 secs
  629. 0.024f, // 2 points: ${($m1 + $b1*2 + 0.024 * $AP) * 5} damage over 10 secs
  630. 0.03f, // 3 points: ${($m1 + $b1*3 + 0.03 * $AP) * 6} damage over 12 secs
  631. 0.03428571f, // 4 points: ${($m1 + $b1*4 + 0.03428571 * $AP) * 7} damage over 14 secs
  632. 0.0375f // 5 points: ${($m1 + $b1*5 + 0.0375 * $AP) * 8} damage over 16 secs
  633. };
  634. uint8 cp = caster->ToPlayer()->GetComboPoints();
  635. if (cp > 5)
  636. cp = 5;
  637. amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * attackpowerPerCombo[cp]);
  638. }
  639. }
  640. void Register() override
  641. {
  642. DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_rupture_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
  643. }
  644. };
  645. AuraScript* GetAuraScript() const override
  646. {
  647. return new spell_rog_rupture_AuraScript();
  648. }
  649. };
  650. // 5938 - Shiv
  651. class spell_rog_shiv : public SpellScriptLoader
  652. {
  653. public:
  654. spell_rog_shiv() : SpellScriptLoader("spell_rog_shiv") { }
  655. class spell_rog_shiv_SpellScript : public SpellScript
  656. {
  657. PrepareSpellScript(spell_rog_shiv_SpellScript);
  658. bool Load() override
  659. {
  660. return GetCaster()->GetTypeId() == TYPEID_PLAYER;
  661. }
  662. bool Validate(SpellInfo const* /*spellInfo*/) override
  663. {
  664. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_SHIV_TRIGGERED))
  665. return false;
  666. return true;
  667. }
  668. void HandleDummy(SpellEffIndex /*effIndex*/)
  669. {
  670. Unit* caster = GetCaster();
  671. if (Unit* unitTarget = GetHitUnit())
  672. caster->CastSpell(unitTarget, SPELL_ROGUE_SHIV_TRIGGERED, true);
  673. }
  674. void Register() override
  675. {
  676. OnEffectHitTarget += SpellEffectFn(spell_rog_shiv_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
  677. }
  678. };
  679. SpellScript* GetSpellScript() const override
  680. {
  681. return new spell_rog_shiv_SpellScript();
  682. }
  683. };
  684. // 1784 - Stealth
  685. class spell_rog_stealth : public SpellScriptLoader
  686. {
  687. public:
  688. spell_rog_stealth() : SpellScriptLoader("spell_rog_stealth") { }
  689. class spell_rog_stealth_AuraScript : public AuraScript
  690. {
  691. PrepareAuraScript(spell_rog_stealth_AuraScript);
  692. bool Validate(SpellInfo const* /*spellInfo*/)
  693. {
  694. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_MASTER_OF_SUBTLETY_PASSIVE) ||
  695. !sSpellMgr->GetSpellInfo(SPELL_ROGUE_MASTER_OF_SUBTLETY_DAMAGE_PERCENT) ||
  696. !sSpellMgr->GetSpellInfo(SPELL_ROGUE_MASTER_OF_SUBTLETY_PERIODIC) ||
  697. !sSpellMgr->GetSpellInfo(SPELL_ROGUE_OVERKILL_TALENT) ||
  698. !sSpellMgr->GetSpellInfo(SPELL_ROGUE_OVERKILL_POWER_REGEN) ||
  699. !sSpellMgr->GetSpellInfo(SPELL_ROGUE_OVERKILL_PERIODIC))
  700. return false;
  701. return true;
  702. }
  703. void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
  704. {
  705. Unit* target = GetTarget();
  706. // Master of Subtlety
  707. if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_ROGUE_MASTER_OF_SUBTLETY_PASSIVE, EFFECT_0))
  708. {
  709. int32 basepoints0 = aurEff->GetAmount();
  710. target->CastCustomSpell(target, SPELL_ROGUE_MASTER_OF_SUBTLETY_DAMAGE_PERCENT, &basepoints0, NULL, NULL, true);
  711. }
  712. // Overkill
  713. if (target->HasAura(SPELL_ROGUE_OVERKILL_TALENT))
  714. target->CastSpell(target, SPELL_ROGUE_OVERKILL_POWER_REGEN, true);
  715. }
  716. void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
  717. {
  718. Unit* target = GetTarget();
  719. // Master of subtlety
  720. if (target->HasAura(SPELL_ROGUE_MASTER_OF_SUBTLETY_PASSIVE))
  721. target->CastSpell(target, SPELL_ROGUE_MASTER_OF_SUBTLETY_PERIODIC, true);
  722. // Overkill
  723. if (target->HasAura(SPELL_ROGUE_OVERKILL_TALENT))
  724. target->CastSpell(target, SPELL_ROGUE_OVERKILL_PERIODIC, true);
  725. }
  726. void Register()
  727. {
  728. AfterEffectApply += AuraEffectApplyFn(spell_rog_stealth_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_MOD_SHAPESHIFT, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
  729. AfterEffectRemove += AuraEffectRemoveFn(spell_rog_stealth_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_MOD_SHAPESHIFT, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
  730. }
  731. };
  732. AuraScript* GetAuraScript() const
  733. {
  734. return new spell_rog_stealth_AuraScript();
  735. }
  736. };
  737. // 57934 - Tricks of the Trade
  738. class spell_rog_tricks_of_the_trade : public SpellScriptLoader
  739. {
  740. public:
  741. spell_rog_tricks_of_the_trade() : SpellScriptLoader("spell_rog_tricks_of_the_trade") { }
  742. class spell_rog_tricks_of_the_trade_AuraScript : public AuraScript
  743. {
  744. PrepareAuraScript(spell_rog_tricks_of_the_trade_AuraScript);
  745. public:
  746. spell_rog_tricks_of_the_trade_AuraScript()
  747. {
  748. _redirectTarget = nullptr;
  749. }
  750. private:
  751. bool Validate(SpellInfo const* /*spellInfo*/) override
  752. {
  753. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST))
  754. return false;
  755. if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC))
  756. return false;
  757. return true;
  758. }
  759. void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
  760. {
  761. if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT)
  762. GetTarget()->ResetRedirectThreat();
  763. }
  764. bool CheckProc(ProcEventInfo& /*eventInfo*/)
  765. {
  766. _redirectTarget = GetTarget()->GetRedirectThreatTarget();
  767. return _redirectTarget != nullptr;
  768. }
  769. void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
  770. {
  771. PreventDefaultAction();
  772. Unit* target = GetTarget();
  773. target->CastSpell(_redirectTarget, SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST, true);
  774. target->CastSpell(target, SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC, true);
  775. Remove(AURA_REMOVE_BY_DEFAULT); // maybe handle by proc charges
  776. }
  777. void Register() override
  778. {
  779. AfterEffectRemove += AuraEffectRemoveFn(spell_rog_tricks_of_the_trade_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
  780. DoCheckProc += AuraCheckProcFn(spell_rog_tricks_of_the_trade_AuraScript::CheckProc);
  781. OnEffectProc += AuraEffectProcFn(spell_rog_tricks_of_the_trade_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
  782. }
  783. private:
  784. Unit* _redirectTarget;
  785. };
  786. AuraScript* GetAuraScript() const override
  787. {
  788. return new spell_rog_tricks_of_the_trade_AuraScript();
  789. }
  790. };
  791. // 59628 - Tricks of the Trade (Proc)
  792. class spell_rog_tricks_of_the_trade_proc : public SpellScriptLoader
  793. {
  794. public:
  795. spell_rog_tricks_of_the_trade_proc() : SpellScriptLoader("spell_rog_tricks_of_the_trade_proc") { }
  796. class spell_rog_tricks_of_the_trade_proc_AuraScript : public AuraScript
  797. {
  798. PrepareAuraScript(spell_rog_tricks_of_the_trade_proc_AuraScript);
  799. void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
  800. {
  801. GetTarget()->ResetRedirectThreat();
  802. }
  803. void Register() override
  804. {
  805. AfterEffectRemove += AuraEffectRemoveFn(spell_rog_tricks_of_the_trade_proc_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
  806. }
  807. };
  808. AuraScript* GetAuraScript() const override
  809. {
  810. return new spell_rog_tricks_of_the_trade_proc_AuraScript();
  811. }
  812. };
  813. class spell_rog_serrated_blades : public SpellScriptLoader
  814. {
  815. public:
  816. spell_rog_serrated_blades() : SpellScriptLoader("spell_rog_serrated_blades") { }
  817. class spell_rog_serrated_blades_SpellScript : public SpellScript
  818. {
  819. PrepareSpellScript(spell_rog_serrated_blades_SpellScript);
  820. void HandleHit()
  821. {
  822. if (AuraEffect* blade = GetCaster()->GetAuraEffectOfRankedSpell(SPELL_ROGUE_SERRATED_BLADES_R1, EFFECT_0))
  823. {
  824. uint8 combo = GetCaster()->ToPlayer()->GetComboPoints();
  825. if (roll_chance_i(blade->GetAmount() * combo))
  826. if (Aura* dot = GetHitUnit()->GetAura(SPELL_ROGUE_RUPTURE, GetCaster()->GetGUID()))
  827. dot->RefreshDuration();
  828. }
  829. }
  830. void Register()
  831. {
  832. OnHit += SpellHitFn(spell_rog_serrated_blades_SpellScript::HandleHit);
  833. }
  834. };
  835. SpellScript* GetSpellScript() const override
  836. {
  837. return new spell_rog_serrated_blades_SpellScript();
  838. }
  839. };
  840. void AddSC_rogue_spell_scripts()
  841. {
  842. new spell_rog_blade_flurry();
  843. new spell_rog_cheat_death();
  844. new spell_rog_crippling_poison();
  845. new spell_rog_cut_to_the_chase();
  846. new spell_rog_deadly_poison();
  847. new spell_rog_killing_spree();
  848. new spell_rog_master_of_subtlety();
  849. new spell_rog_nerves_of_steel();
  850. new spell_rog_overkill();
  851. new spell_rog_preparation();
  852. new spell_rog_prey_on_the_weak();
  853. new spell_rog_recuperate();
  854. new spell_rog_rupture();
  855. new spell_rog_shiv();
  856. new spell_rog_stealth();
  857. new spell_rog_tricks_of_the_trade();
  858. new spell_rog_tricks_of_the_trade_proc();
  859. new spell_rog_serrated_blades();
  860. }