diff options
-rw-r--r-- | sql/updates/world/2012_11_13_06_world_trinity_string.sql (renamed from sql/updates/world/2012_11_13_00_world_trinity_string.sql) | 0 | ||||
-rw-r--r-- | sql/updates/world/2012_11_14_00_world_sai.sql | 16 | ||||
-rw-r--r-- | src/server/scripts/World/boss_emerald_dragons.cpp | 310 |
3 files changed, 192 insertions, 134 deletions
diff --git a/sql/updates/world/2012_11_13_00_world_trinity_string.sql b/sql/updates/world/2012_11_13_06_world_trinity_string.sql index 2834a8f900b..2834a8f900b 100644 --- a/sql/updates/world/2012_11_13_00_world_trinity_string.sql +++ b/sql/updates/world/2012_11_13_06_world_trinity_string.sql diff --git a/sql/updates/world/2012_11_14_00_world_sai.sql b/sql/updates/world/2012_11_14_00_world_sai.sql new file mode 100644 index 00000000000..98467fe4f3a --- /dev/null +++ b/sql/updates/world/2012_11_14_00_world_sai.sql @@ -0,0 +1,16 @@ +SET @ENTRY_SPIRIT_SHADE := 15261; +SET @ENTRY_LETHON := 14888; +SET @SPELL_DARK_OFFERING := 24804; + +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY_SPIRIT_SHADE; +UPDATE `creature_template` SET `AIName`= '',`ScriptName`= 'npc_spirit_shade' WHERE `entry`=@ENTRY_SPIRIT_SHADE; + +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY_SPIRIT_SHADE AND `source_type`=0; + +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY_SPIRIT_SHADE; +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`auras`) VALUES +(@ENTRY_SPIRIT_SHADE,0,0,0, '24809'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=@SPELL_DARK_OFFERING; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,1,@SPELL_DARK_OFFERING,0,0,31,0,3,@ENTRY_LETHON,0,0,0, '', 'Dark offering can only target Lethon'); diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp index abb20130ef8..65677959135 100644 --- a/src/server/scripts/World/boss_emerald_dragons.cpp +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -22,6 +22,7 @@ #include "SpellScript.h" #include "Spell.h" #include "SpellAuraEffects.h" +#include "PassiveAI.h" // // Emerald Dragon NPCs and IDs (kept here for reference) @@ -91,14 +92,12 @@ struct emerald_dragonAI : public WorldBossAI { emerald_dragonAI(Creature* creature) : WorldBossAI(creature) { -// me->m_CombatDistance = 12.0f; -// me->m_SightDistance = 60.0f; } void Reset() { - _Reset(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + WorldBossAI::Reset(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); me->SetReactState(REACT_AGGRESSIVE); DoCast(me, SPELL_MARK_OF_NATURE_AURA, true); events.ScheduleEvent(EVENT_TAIL_SWEEP, 4000); @@ -109,7 +108,8 @@ struct emerald_dragonAI : public WorldBossAI // Target killed during encounter, mark them as suspectible for Aura Of Nature void KilledUnit(Unit* who) { - who->CastSpell(who, SPELL_MARK_OF_NATURE, true); + if (who->GetTypeId() == TYPEID_PLAYER) + who->CastSpell(who, SPELL_MARK_OF_NATURE, true); } // Execute and reschedule base events shared between all Emerald Dragons @@ -216,109 +216,6 @@ class npc_dream_fog : public CreatureScript }; /* - * --- Spell: Dream Fog - */ - -class DreamFogTargetSelector -{ - public: - DreamFogTargetSelector() { } - - bool operator()(WorldObject* object) const - { - return object->ToUnit() && object->ToUnit()->HasAura(SPELL_SLEEP); - } -}; - -class spell_dream_fog_sleep : public SpellScriptLoader -{ - public: - spell_dream_fog_sleep() : SpellScriptLoader("spell_dream_fog_sleep") { } - - class spell_dream_fog_sleep_SpellScript : public SpellScript - { - PrepareSpellScript(spell_dream_fog_sleep_SpellScript); - - void FilterTargets(std::list<WorldObject*>& unitList) - { - unitList.remove_if(DreamFogTargetSelector()); - } - - void Register() - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dream_fog_sleep_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const - { - return new spell_dream_fog_sleep_SpellScript(); - } -}; - -/* - * --- Spell: Mark of Nature - */ - -class MarkOfNatureTargetSelector -{ - public: - MarkOfNatureTargetSelector() { } - - bool operator()(WorldObject* object) const - { - if (Unit* unit = object->ToUnit()) - // return anyone that isn't tagged or already under the influence of Aura of Nature - return !(unit->HasAura(SPELL_MARK_OF_NATURE) && !unit->HasAura(SPELL_AURA_OF_NATURE)); - return true; - } -}; - -class spell_mark_of_nature : public SpellScriptLoader -{ - public: - spell_mark_of_nature() : SpellScriptLoader("spell_mark_of_nature") { } - - class spell_mark_of_nature_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mark_of_nature_SpellScript); - - bool Validate(SpellInfo const* /*spellInfo*/) - { - if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_NATURE)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_AURA_OF_NATURE)) - return false; - return true; - } - - void FilterTargets(std::list<WorldObject*>& targets) - { - targets.remove_if(MarkOfNatureTargetSelector()); - } - - void HandleEffect(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - - if (GetHitUnit()) - GetHitUnit()->CastSpell(GetHitUnit(), SPELL_AURA_OF_NATURE, true); - } - - void Register() - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_nature_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_mark_of_nature_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA); - } - }; - - SpellScript* GetSpellScript() const - { - return new spell_mark_of_nature_SpellScript(); - } -}; - -/* * --- * --- Dragonspecific scripts and handling: YSONDRE * --- @@ -355,7 +252,6 @@ class boss_ysondre : public CreatureScript void Reset() { _stage = 1; - _Reset(); emerald_dragonAI::Reset(); events.ScheduleEvent(EVENT_LIGHTNING_WAVE, 12000); } @@ -394,7 +290,7 @@ class boss_ysondre : public CreatureScript } private: - uint8 _stage; + uint8 _stage; }; CreatureAI* GetAI(Creature* creature) const @@ -409,8 +305,6 @@ class boss_ysondre : public CreatureScript * --- * * TODO: - * - NPC helper for spirit shades(?) - * - Spirit shade NPC moves towards Lethon and heals him if close enough (each shade heals for 15000 HP) * - Spell: Shadow bolt whirl casts needs custom handling (spellscript) */ @@ -424,7 +318,12 @@ enum LethonSpells { SPELL_DRAW_SPIRIT = 24811, SPELL_SHADOW_BOLT_WHIRL = 24834, - SPELL_SPIRIT_SHADE_VISUAL = 24908, + SPELL_DARK_OFFERING = 24804, +}; + +enum LethonCreatures +{ + NPC_SPIRIT_SHADE = 15261, }; class boss_lethon : public CreatureScript @@ -441,7 +340,6 @@ class boss_lethon : public CreatureScript void Reset() { _stage = 1; - _Reset(); emerald_dragonAI::Reset(); events.ScheduleEvent(EVENT_SHADOW_BOLT_WHIRL, 10000); } @@ -462,12 +360,22 @@ class boss_lethon : public CreatureScript } } + void SpellHitTarget(Unit* target, SpellInfo const* spell) + { + if (spell->Id == SPELL_DRAW_SPIRIT && target->GetTypeId() == TYPEID_PLAYER) + { + Position targetPos; + target->GetPosition(&targetPos); + me->GetMap()->SummonCreature(NPC_SPIRIT_SHADE, targetPos, NULL, 50000, (Unit*)this); + } + } + void ExecuteEvent(uint32 const eventId) { switch (eventId) { case EVENT_SHADOW_BOLT_WHIRL: - DoCast(me, SPELL_SHADOW_BOLT_WHIRL, true); + me->CastSpell((Unit*)NULL, SPELL_SHADOW_BOLT_WHIRL, false); events.ScheduleEvent(EVENT_SHADOW_BOLT_WHIRL, urand(15000, 30000)); break; default: @@ -477,7 +385,7 @@ class boss_lethon : public CreatureScript } private: - uint8 _stage; + uint8 _stage; }; CreatureAI* GetAI(Creature* creature) const @@ -486,6 +394,42 @@ class boss_lethon : public CreatureScript } }; +class npc_spirit_shade : public CreatureScript +{ + public: + npc_spirit_shade() : CreatureScript("npc_spirit_shade") { } + + struct npc_spirit_shadeAI : public PassiveAI + { + npc_spirit_shadeAI(Creature* creature) : PassiveAI(creature), _summonerGuid(0) + { + } + + void IsSummonedBy(Unit* summoner) + { + _summonerGuid = summoner->GetGUID(); + me->GetMotionMaster()->MoveFollow(summoner, 0.0f, 0.0f); + } + + void MovementInform(uint32 moveType, uint32 data) + { + if (moveType == FOLLOW_MOTION_TYPE && data == _summonerGuid) + { + me->CastSpell((Unit*)NULL, SPELL_DARK_OFFERING, false); + me->DespawnOrUnsummon(1000); + } + } + + private: + uint64 _summonerGuid; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_spirit_shadeAI(creature); + } +}; + /* * --- * --- Dragonspecific scripts and handling: EMERISS @@ -519,7 +463,6 @@ class boss_emeriss : public CreatureScript void Reset() { _stage = 1; - _Reset(); emerald_dragonAI::Reset(); events.ScheduleEvent(EVENT_VOLATILE_INFECTION, 12000); } @@ -562,7 +505,7 @@ class boss_emeriss : public CreatureScript } private: - uint8 _stage; + uint8 _stage; }; CreatureAI* GetAI(Creature* creature) const @@ -607,10 +550,6 @@ class boss_taerar : public CreatureScript { boss_taerarAI(Creature* creature) : emerald_dragonAI(creature) { - _stage = 1; - _shades = 0; - _banished = false; - _banishedTimer = 0; } void Reset() @@ -622,7 +561,6 @@ class boss_taerar : public CreatureScript _banished = false; _banishedTimer = 0; - _Reset(); emerald_dragonAI::Reset(); events.ScheduleEvent(EVENT_ARCANE_BLAST, 12000); events.ScheduleEvent(EVENT_BELLOWING_ROAR, 30000); @@ -655,11 +593,11 @@ class boss_taerar : public CreatureScript uint32 count = sizeof(TaerarShadeSpells) / sizeof(uint32); for (uint32 i = 0; i < count; ++i) - DoCastVictim(TaerarShadeSpells[i], true); + DoCast(me->getVictim(), TaerarShadeSpells[i], true); _shades += count; DoCast(SPELL_SHADE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); me->SetReactState(REACT_PASSIVE); ++_stage; @@ -696,7 +634,7 @@ class boss_taerar : public CreatureScript { _banished = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); me->RemoveAurasDueToSpell(SPELL_SHADE); me->SetReactState(REACT_AGGRESSIVE); } @@ -714,10 +652,10 @@ class boss_taerar : public CreatureScript } private: - bool _banished; // used for shades activation testing - uint32 _banishedTimer; // counter for banishment timeout - uint8 _shades; // keep track of how many shades are dead - uint8 _stage; // check which "shade phase" we're at (75-50-25 percentage counters) + bool _banished; // used for shades activation testing + uint32 _banishedTimer; // counter for banishment timeout + uint8 _shades; // keep track of how many shades are dead + uint8 _stage; // check which "shade phase" we're at (75-50-25 percentage counters) }; CreatureAI* GetAI(Creature* creature) const @@ -726,18 +664,122 @@ class boss_taerar : public CreatureScript } }; +/* + * --- Spell: Dream Fog + */ + +class DreamFogTargetSelector +{ + public: + DreamFogTargetSelector() { } + + bool operator()(WorldObject* object) + { + if (Unit* unit = object->ToUnit()) + return unit->HasAura(SPELL_SLEEP); + return true; + } +}; + +class spell_dream_fog_sleep : public SpellScriptLoader +{ + public: + spell_dream_fog_sleep() : SpellScriptLoader("spell_dream_fog_sleep") { } + + class spell_dream_fog_sleep_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dream_fog_sleep_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(DreamFogTargetSelector()); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dream_fog_sleep_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dream_fog_sleep_SpellScript(); + } +}; + +/* + * --- Spell: Mark of Nature + */ + +class MarkOfNatureTargetSelector +{ + public: + MarkOfNatureTargetSelector() { } + + bool operator()(WorldObject* object) + { + // return those not tagged or already under the influence of Aura of Nature + if (Unit* unit = object->ToUnit()) + return !(unit->HasAura(SPELL_MARK_OF_NATURE) && !unit->HasAura(SPELL_AURA_OF_NATURE)); + return true; + } +}; + +class spell_mark_of_nature : public SpellScriptLoader +{ + public: + spell_mark_of_nature() : SpellScriptLoader("spell_mark_of_nature") { } + + class spell_mark_of_nature_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mark_of_nature_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_NATURE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_AURA_OF_NATURE)) + return false; + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(MarkOfNatureTargetSelector()); + } + + void HandleEffect(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_AURA_OF_NATURE, true); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_nature_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_mark_of_nature_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_mark_of_nature_SpellScript(); + } +}; + void AddSC_emerald_dragons() { // helper NPC scripts new npc_dream_fog(); - - // dragon spellscripts - new spell_dream_fog_sleep(); - new spell_mark_of_nature(); + new npc_spirit_shade(); // dragons new boss_ysondre(); new boss_taerar(); new boss_emeriss(); new boss_lethon(); + + // dragon spellscripts + new spell_dream_fog_sleep(); + new spell_mark_of_nature(); }; |