PageRenderTime 111ms CodeModel.GetById 9ms app.highlight 95ms RepoModel.GetById 1ms app.codeStats 0ms

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