diff options
| author | joschiwald <joschiwald.trinity@gmail.com> | 2014-01-30 02:40:12 +0100 | 
|---|---|---|
| committer | joschiwald <joschiwald.trinity@gmail.com> | 2014-01-30 02:40:12 +0100 | 
| commit | acd46085d1f496657e27e0d5f823f53d466702dc (patch) | |
| tree | 2b489957b50a475d8c410cc4a8ab71097c879714 /src/server/scripts | |
| parent | 747184a7c0dc200b9c2c8607a3e1dd990161278e (diff) | |
Core/Spells: drop last leftovers of hardcoded spell target selection and move it into spellscripts
Closes #1719
Closes #3186
Diffstat (limited to 'src/server/scripts')
| -rw-r--r-- | src/server/scripts/Spells/spell_dk.cpp | 273 | 
1 files changed, 258 insertions, 15 deletions
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index e2e4d30541c..e8108f03e7d 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -25,6 +25,7 @@  #include "ScriptMgr.h"  #include "SpellScript.h"  #include "SpellAuraEffects.h" +#include "Containers.h"  enum DeathKnightSpells  { @@ -49,6 +50,8 @@ enum DeathKnightSpells      SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622,      SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART          = 64962,      SPELL_DK_ITEM_T8_MELEE_4P_BONUS             = 64736, +    SPELL_DK_MASTER_OF_GHOULS                   = 52143, +    SPELL_DK_RAISE_DEAD_USE_REAGENT             = 48289,      SPELL_DK_RUNIC_POWER_ENERGIZE               = 49088,      SPELL_DK_SCENT_OF_BLOOD                     = 50422,      SPELL_DK_SCOURGE_STRIKE_TRIGGERED           = 70890, @@ -63,6 +66,11 @@ enum DeathKnightSpellIcons      DK_ICON_ID_IMPROVED_DEATH_STRIKE            = 2751  }; +enum Misc +{ +    NPC_DK_GHOUL                                = 26125 +}; +  // 50462 - Anti-Magic Shell (on raid member)  class spell_dk_anti_magic_shell_raid : public SpellScriptLoader  { @@ -311,6 +319,28 @@ class spell_dk_blood_gorged : public SpellScriptLoader          }  }; +class CorpseExplosionCheck +{ +public: +    explicit CorpseExplosionCheck(uint64 casterGUID) : _casterGUID(casterGUID) { } + +    bool operator()(WorldObject* obj) const +    { +        if (Unit* target = obj->ToUnit()) +        { +            if ((target->isDead() || (target->GetEntry() == NPC_DK_GHOUL && target->GetOwnerGUID() == _casterGUID)) +                && !(target->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) +                && target->GetDisplayId() == target->GetNativeDisplayId()) +                return false; +        } + +        return true; +    } + +private: +    uint64 _casterGUID; +}; +  // 49158 - Corpse Explosion (51325, 51326, 51327, 51328)  class spell_dk_corpse_explosion : public SpellScriptLoader  { @@ -321,41 +351,87 @@ class spell_dk_corpse_explosion : public SpellScriptLoader          {              PrepareSpellScript(spell_dk_corpse_explosion_SpellScript); -            bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE +            bool Validate(SpellInfo const* spellInfo) OVERRIDE              { -                if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE)) -                    return false; -                if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL)) +                if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) +                    || !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE) +                    || !sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL) +                    || !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue()))                      return false;                  return true;              } -            void HandleDummy(SpellEffIndex /*effIndex*/) +            bool Load() OVERRIDE +            { +                _target = NULL; +                return true; +            } + +            void CheckTarget(WorldObject*& target) +            { +                if (CorpseExplosionCheck(GetCaster()->GetGUID())(target)) +                    target = NULL; + +                _target = target; +            } + +            void CheckTargets(std::list<WorldObject*>& targets) +            { +                WorldObject* target = _target; +                if (!target) +                { +                    targets.remove_if(CorpseExplosionCheck(GetCaster()->GetGUID())); +                    if (targets.empty()) +                    { +                        FinishCast(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); +                        return; +                    } +                    target = Trinity::Containers::SelectRandomContainerElement(targets); +                    targets.clear(); +                    targets.push_back(target); +                } +                else +                    targets.clear(); +            } + +            void HandleDamage(SpellEffIndex effIndex, Unit* target) +            { +                if (effIndex == EFFECT_0) +                    GetCaster()->CastCustomSpell(GetSpellInfo()->Effects[EFFECT_1].CalcValue(), SPELLVALUE_BASE_POINT0, GetEffectValue(), target, true); +                else if (effIndex == EFFECT_1) +                    GetCaster()->CastCustomSpell(GetEffectValue(), SPELLVALUE_BASE_POINT0, GetSpell()->CalculateDamage(EFFECT_0, NULL), target, true); +            } + +            void HandleCorpseExplosion(SpellEffIndex effIndex)              {                  if (Unit* unitTarget = GetHitUnit())                  { -                    int32 bp = 0;                      if (unitTarget->IsAlive())  // Living ghoul as a target                      { -                        bp = int32(unitTarget->CountPctFromMaxHealth(25)); -                        unitTarget->CastCustomSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, &bp, NULL, NULL, false); +                        unitTarget->CastSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, false); +                        // Corpse Explosion (Suicide) and Set corpse look handled in SpellScript of SPELL_DK_GHOUL_EXPLODE                      }                      else                        // Some corpse                      { -                        bp = GetEffectValue(); -                        GetCaster()->CastCustomSpell(unitTarget, GetSpellInfo()->Effects[EFFECT_1].CalcValue(), &bp, NULL, NULL, true); +                        HandleDamage(effIndex, unitTarget);                          // Corpse Explosion (Suicide)                          unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true); +                        // Set corpse look +                        GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);                      } -                    // Set corpse look -                    GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);                  }              }              void Register() OVERRIDE              { -                OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); +                OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTarget, EFFECT_0, TARGET_UNIT_TARGET_ANY); +                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); +                OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_0, SPELL_EFFECT_DUMMY); +                OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_1, SPELL_EFFECT_DUMMY);              } + +        private: +            WorldObject* _target;          };          SpellScript* GetSpellScript() const OVERRIDE @@ -616,24 +692,34 @@ class spell_dk_ghoul_explode : public SpellScriptLoader          {              PrepareSpellScript(spell_dk_ghoul_explode_SpellScript); -            bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE +            bool Validate(SpellInfo const* spellInfo) OVERRIDE              { -                if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED)) +                if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) +                    || spellInfo->Effects[EFFECT_2].CalcValue() <= 0)                      return false;                  return true;              } +            void HandleDamage(SpellEffIndex /*effIndex*/) +            { +                int32 value = int32(GetCaster()->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster()))); +                SetEffectValue(value); +            } +              void Suicide(SpellEffIndex /*effIndex*/)              {                  if (Unit* unitTarget = GetHitUnit())                  {                      // Corpse Explosion (Suicide)                      unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true); +                    // Set corpse look +                    GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);                  }              }              void Register() OVERRIDE              { +                OnEffectLaunchTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);                  OnEffectHitTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::Suicide, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE);              }          }; @@ -940,6 +1026,162 @@ class spell_dk_presence : public SpellScriptLoader          }  }; +class RaiseDeadCheck +{ +    public: +        explicit RaiseDeadCheck(Player const* caster) : _caster(caster) { } + +        bool operator()(WorldObject* obj) const +        { +            if (Unit* target = obj->ToUnit()) +            { +                if (!target->IsAlive() +                    && _caster->isHonorOrXPTarget(target) +                    && target->GetCreatureType() == CREATURE_TYPE_HUMANOID +                    && target->GetDisplayId() == target->GetNativeDisplayId()) +                    return false; +            } + +            return true; +        } + +    private: +        Player const* _caster; +}; + +// 46584 - Raise Dead +class spell_dk_raise_dead : public SpellScriptLoader +{ +    public: +        spell_dk_raise_dead() : SpellScriptLoader("spell_dk_raise_dead") { } + +        class spell_dk_raise_dead_SpellScript : public SpellScript +        { +            PrepareSpellScript(spell_dk_raise_dead_SpellScript); + +            bool Validate(SpellInfo const* spellInfo) OVERRIDE +            { +                if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue()) +                    || !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_2].CalcValue()) +                    || !sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT) +                    || !sSpellMgr->GetSpellInfo(SPELL_DK_MASTER_OF_GHOULS)) +                    return false; +                return true; +            } + +            bool Load() OVERRIDE +            { +                _result = SPELL_CAST_OK; +                _corpse = false; +                return GetCaster()->GetTypeId() == TYPEID_PLAYER; +            } + +            SpellCastResult CheckCast() +            { +                /// process spell target selection before cast starts +                /// targets of effect_1 are used to check cast +                GetSpell()->SelectSpellTargets(); +                /// cleanup spell target map, and fill it again on normal way +                GetSpell()->CleanupTargetList(); +                /// _result is set in spell target selection +                return _result; +            } + +            SpellCastResult CheckReagents() +            { +                /// @workaround: there is no access to castresult of other spells, check it manually +                SpellInfo const* reagentSpell = sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT); +                Player* player = GetCaster()->ToPlayer(); +                if (!player->CanNoReagentCast(reagentSpell)) +                { +                    for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++) +                    { +                        if (reagentSpell->Reagent[i] <= 0) +                            continue; + +                        if (!player->HasItemCount(reagentSpell->Reagent[i], reagentSpell->ReagentCount[i])) +                        { +                            Spell::SendCastResult(player, reagentSpell, 0, SPELL_FAILED_REAGENTS); +                            return SPELL_FAILED_DONT_REPORT; +                        } +                    } +                } +                return SPELL_CAST_OK; +            } + +            void CheckTargets(std::list<WorldObject*>& targets) +            { +                targets.remove_if(RaiseDeadCheck(GetCaster()->ToPlayer())); + +                if (targets.empty()) +                { +                    if (GetSpell()->getState() == SPELL_STATE_PREPARING) +                        _result = CheckReagents(); + +                    return; +                } + +                WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); +                targets.clear(); +                targets.push_back(target); +                _corpse = true; +            } + +            void CheckTarget(WorldObject*& target) +            { +                // Don't add caster to target map, if we found a corpse to raise dead +                if (_corpse) +                    target = NULL; +            } + +            void ConsumeReagents() +            { +                // No corpse found, take reagents +                if (!_corpse) +                    GetCaster()->CastSpell(GetCaster(), SPELL_DK_RAISE_DEAD_USE_REAGENT, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); +            } + +            uint32 GetGhoulSpellId() +            { +                // Do we have talent Master of Ghouls? +                if (GetCaster()->HasAura(SPELL_DK_MASTER_OF_GHOULS)) +                    // summon as pet +                    return GetSpellInfo()->Effects[EFFECT_2].CalcValue(); + +                // or guardian +                return GetSpellInfo()->Effects[EFFECT_1].CalcValue(); +            } + +            void HandleRaiseDead(SpellEffIndex /*effIndex*/) +            { +                SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(GetGhoulSpellId()); +                SpellCastTargets targets; +                targets.SetDst(*GetHitUnit()); + +                GetCaster()->CastSpell(targets, spellInfo, NULL, TRIGGERED_FULL_MASK); +            } + +            void Register() OVERRIDE +            { +                OnCheckCast += SpellCheckCastFn(spell_dk_raise_dead_SpellScript::CheckCast); +                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); +                OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTarget, EFFECT_2, TARGET_UNIT_CASTER); +                OnCast += SpellCastFn(spell_dk_raise_dead_SpellScript::ConsumeReagents); +                OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); +                OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY); +            } + +        private: +            SpellCastResult _result; +            bool _corpse; +        }; + +        SpellScript* GetSpellScript() const OVERRIDE +        { +            return new spell_dk_raise_dead_SpellScript(); +        } +}; +  // 59754 Rune Tap - Party  class spell_dk_rune_tap_party : public SpellScriptLoader  { @@ -1224,6 +1466,7 @@ void AddSC_deathknight_spell_scripts()      new spell_dk_improved_frost_presence();      new spell_dk_improved_unholy_presence();      new spell_dk_presence(); +    new spell_dk_raise_dead();      new spell_dk_rune_tap_party();      new spell_dk_scent_of_blood();      new spell_dk_scourge_strike();  | 
