diff options
| author | Vincent-Michael <Vincent_Michael@gmx.de> | 2014-04-05 20:43:05 +0200 |
|---|---|---|
| committer | Vincent-Michael <Vincent_Michael@gmx.de> | 2014-04-05 20:43:05 +0200 |
| commit | e4b14b943d3a2aa5d7b41107adc8c5236b86d1af (patch) | |
| tree | 2ef54a0bc7d4f5385b9266afe528265ed9f35f8d /src/server/scripts/Northrend | |
| parent | a903c335024d0ef4a3d9899587fcd0b10a92b31e (diff) | |
| parent | 29610b250dd5017f068264d9b1a37748c9f30feb (diff) | |
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts:
sql/old/3.3.5a/TDB52_to_TDB53_updates/world/2013_07_24_00_world_spell_script_names.sql
sql/updates/world/2013_07_24_00_world_spell_script_names.sql
sql/updates/world/2013_07_24_00_world_spell_script_names_335.sql
src/server/game/Achievements/AchievementMgr.cpp
src/server/game/Achievements/AchievementMgr.h
src/server/game/Battlegrounds/ArenaTeamMgr.cpp
src/server/game/Chat/ChatLink.cpp
src/server/game/DataStores/DBCStores.cpp
src/server/game/DataStores/DBCStructure.h
src/server/game/DataStores/DBCfmt.h
src/server/game/Entities/DynamicObject/DynamicObject.h
src/server/game/Entities/Object/Object.cpp
src/server/game/Entities/Player/Player.cpp
src/server/game/Entities/Unit/StatSystem.cpp
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Entities/Unit/Unit.h
src/server/game/Groups/Group.cpp
src/server/game/Handlers/QuestHandler.cpp
src/server/game/Miscellaneous/SharedDefines.h
src/server/game/Spells/Auras/SpellAuraEffects.cpp
src/server/game/Spells/Auras/SpellAuras.cpp
src/server/game/World/World.h
src/server/scripts/Commands/cs_character.cpp
src/server/scripts/Commands/cs_lookup.cpp
src/server/scripts/Commands/cs_titles.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp
src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
src/server/scripts/Kalimdor/zone_darkshore.cpp
src/server/scripts/Kalimdor/zone_mulgore.cpp
src/server/scripts/Kalimdor/zone_tanaris.cpp
src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
src/server/scripts/Spells/spell_dk.cpp
src/server/scripts/Spells/spell_mage.cpp
src/server/scripts/Spells/spell_rogue.cpp
src/server/shared/Database/Implementation/CharacterDatabase.cpp
src/server/shared/Database/Implementation/CharacterDatabase.h
src/tools/vmap4_extractor/mpq_libmpq04.h
Diffstat (limited to 'src/server/scripts/Northrend')
35 files changed, 3341 insertions, 577 deletions
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index efe439de440..31c565e5be2 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -88,6 +88,9 @@ class boss_prince_taldaram : public CreatureScript boss_prince_taldaramAI(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM) { me->SetDisableGravity(true); + _flameSphereTargetGUID = 0; + _embraceTargetGUID = 0; + _embraceTakenDamage = 0; } void Reset() OVERRIDE @@ -283,7 +286,10 @@ class npc_prince_taldaram_flame_sphere : public CreatureScript struct npc_prince_taldaram_flame_sphereAI : public ScriptedAI { - npc_prince_taldaram_flame_sphereAI(Creature* creature) : ScriptedAI(creature) { } + npc_prince_taldaram_flame_sphereAI(Creature* creature) : ScriptedAI(creature) + { + _flameSphereTargetGUID = 0; + } void Reset() OVERRIDE { diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp index 2fe619a5367..1281d40fe5c 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp @@ -26,30 +26,22 @@ enum Spells { SPELL_MIND_FLAY = 52586, - H_SPELL_MIND_FLAY = 59367, SPELL_CURSE_OF_FATIGUE = 52592, - H_SPELL_CURSE_OF_FATIGUE = 59368, SPELL_FRENZY = 28747, //maybe 53361 SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439 SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735 - H_SPELL_ACID_SPLASH = 59363, SPELL_ACID_SPLASH = 52446, SPELL_CHARGE = 16979, //maybe is another spell SPELL_BACKSTAB = 52540, SPELL_SHADOW_BOLT = 52534, - H_SPELL_SHADOW_BOLT = 59357, SPELL_SHADOW_NOVA = 52535, - H_SPELL_SHADOW_NOVA = 59358, SPELL_STRIKE = 52532, SPELL_CLEAVE = 49806, SPELL_ENRAGE = 52470, SPELL_INFECTED_BITE = 52469, - H_SPELL_INFECTED_BITE = 59364, SPELL_WEB_WRAP = 52086, //the spell is not working properly SPELL_BLINDING_WEBS = 52524, - H_SPELL_BLINDING_WEBS = 59365, - SPELL_POSION_SPRAY = 52493, - H_SPELL_POSION_SPRAY = 59366 + SPELL_POSION_SPRAY = 52493 }; enum Mobs @@ -69,7 +61,7 @@ enum Yells SAY_SEND_GROUP = 5 }; -const Position SpawnPoint[] = +Position const SpawnPoint[] = { { 566.164f, 682.087f, 769.079f, 2.21657f }, { 529.042f, 706.941f, 777.298f, 1.0821f }, @@ -81,444 +73,573 @@ const Position SpawnPoint[] = { 552.625f, 706.408f, 777.177f, 3.4383f } }; +enum Events +{ + EVENT_SUMMON = 1, + EVENT_MIND_FLAY, + EVENT_CURSE_FATIGUE +}; + class boss_krik_thir : public CreatureScript { -public: - boss_krik_thir() : CreatureScript("boss_krik_thir") { } + public: + boss_krik_thir() : CreatureScript("boss_krik_thir") { } - struct boss_krik_thirAI : public ScriptedAI - { - boss_krik_thirAI(Creature* creature) : ScriptedAI(creature) + struct boss_krik_thirAI : public BossAI { - instance = creature->GetInstanceScript(); - } + boss_krik_thirAI(Creature* creature) : BossAI(creature, DATA_KRIKTHIR_THE_GATEWATCHER) { } - InstanceScript* instance; + void Reset() OVERRIDE + { + _Reset(); + } - uint32 uiMindFlayTimer; - uint32 uiCurseFatigueTimer; - uint32 uiSummonTimer; + void EnterCombat(Unit* /*who*/) OVERRIDE + { + Talk(SAY_AGGRO); + _EnterCombat(); + Summon(); - void Reset() OVERRIDE - { - uiMindFlayTimer = 15*IN_MILLISECONDS; - uiCurseFatigueTimer = 12*IN_MILLISECONDS; + events.ScheduleEvent(EVENT_SUMMON, 15000); + events.ScheduleEvent(EVENT_MIND_FLAY, 15000); + events.ScheduleEvent(EVENT_CURSE_FATIGUE, 12000); + } - instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, NOT_STARTED); - } + void Summon() + { + for (uint8 i = 0; i < 8; i++) + { + me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[i], TEMPSUMMON_TIMED_DESPAWN, 25000); + uint32 summon_entry = (i == 4 || i == 5 || i == 6) ? NPC_SKITTERING_INFECTIOR : NPC_SKITTERING_SWARMER; + me->SummonCreature(summon_entry, SpawnPoint[i], TEMPSUMMON_TIMED_DESPAWN, 25000); + } + } - void EnterCombat(Unit* /*who*/) OVERRIDE - { - Talk(SAY_AGGRO); - Summon(); - uiSummonTimer = 15*IN_MILLISECONDS; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, IN_PROGRESS); - } + events.Update(diff); - void Summon() - { - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[0], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[0], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[1], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[1], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[2], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[2], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[3], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[3], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_INFECTIOR, SpawnPoint[4], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[4], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_INFECTIOR, SpawnPoint[5], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[5], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_INFECTIOR, SpawnPoint[6], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[6], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[7], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[7], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SUMMON: + Summon(); + events.ScheduleEvent(EVENT_SUMMON, 15000); + break; + case EVENT_MIND_FLAY: + DoCastVictim(SPELL_MIND_FLAY); + events.ScheduleEvent(EVENT_MIND_FLAY, 15000); + break; + case EVENT_CURSE_FATIGUE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_CURSE_OF_FATIGUE); + events.ScheduleEvent(EVENT_CURSE_FATIGUE, 10000); + break; + default: + break; + } + } - if (uiSummonTimer <= diff) - { - Summon(); - uiSummonTimer = 15*IN_MILLISECONDS; - } else uiSummonTimer -= diff; + if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) + DoCast(me, SPELL_FRENZY, true); - if (uiMindFlayTimer <= diff) - { - DoCastVictim(SPELL_MIND_FLAY); - uiMindFlayTimer = 15*IN_MILLISECONDS; - } else uiMindFlayTimer -= diff; + DoMeleeAttackIfReady(); + } - if (uiCurseFatigueTimer <= diff) + void JustDied(Unit* /*killer*/) OVERRIDE { - //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically." - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CURSE_OF_FATIGUE); - if (Unit* tankTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - DoCast(tankTarget, SPELL_CURSE_OF_FATIGUE); - - uiCurseFatigueTimer = 10*IN_MILLISECONDS; - } else uiCurseFatigueTimer -= diff; - - if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) - DoCast(me, SPELL_FRENZY, true); - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(SAY_DEATH); + Talk(SAY_DEATH); + _JustDied(); + } - instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, DONE); - } + void KilledUnit(Unit* victim) OVERRIDE + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; - void KilledUnit(Unit* victim) OVERRIDE - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; + Talk(SAY_SLAY); + } - Talk(SAY_SLAY); - } + void JustSummoned(Creature* summoned) OVERRIDE + { + summoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + } + }; - void JustSummoned(Creature* summoned) OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - summoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + return GetAzjolNerubAI<boss_krik_thirAI>(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return GetInstanceAI<boss_krik_thirAI>(creature); - } }; class npc_skittering_infector : public CreatureScript { -public: - npc_skittering_infector() : CreatureScript("npc_skittering_infector") { } + public: + npc_skittering_infector() : CreatureScript("npc_skittering_infector") { } + + struct npc_skittering_infectorAI : public ScriptedAI + { + npc_skittering_infectorAI(Creature* creature) : ScriptedAI(creature) { } - struct npc_skittering_infectorAI : public ScriptedAI - { - npc_skittering_infectorAI(Creature* creature) : ScriptedAI(creature) { } + void JustDied(Unit* /*killer*/) OVERRIDE + { + DoCastAOE(SPELL_ACID_SPLASH); + } + }; - void JustDied(Unit* /*killer*/) OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - //The spell is not working propperly - DoCastVictim(SPELL_ACID_SPLASH, true); + return GetAzjolNerubAI<npc_skittering_infectorAI>(creature); } - }; +}; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_skittering_infectorAI(creature); - } +enum TrashEvents +{ + // Anubar Skrimisher + EVENT_ANUBAR_CHARGE = 1, + EVENT_BACKSTAB, + + // Anubar Shadowcaster + EVENT_SHADOW_BOLT, + EVENT_SHADOW_NOVA, + + // Anubar Warrior + EVENT_STRIKE, + EVENT_CLEAVE, + + // Watcher Gashra + EVENT_WEB_WRAP_GASHRA, + EVENT_INFECTED_BITE_GASHRA, + + // Watcher Narjil + EVENT_WEB_WRAP_NARJIL, + EVENT_INFECTED_BITE_NARJIL, + EVENT_BINDING_WEBS, + + // Watcher Silthik + EVENT_WEB_WRAP_SILTHIK, + EVENT_INFECTED_BITE_SILTHIK, + EVENT_POISON_SPRAY }; class npc_anub_ar_skirmisher : public CreatureScript { -public: - npc_anub_ar_skirmisher() : CreatureScript("npc_anub_ar_skirmisher") { } - - struct npc_anub_ar_skirmisherAI : public ScriptedAI - { - npc_anub_ar_skirmisherAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 uiChargeTimer; - uint32 uiBackstabTimer; + public: + npc_anub_ar_skirmisher() : CreatureScript("npc_anub_ar_skirmisher") { } - void Reset() OVERRIDE + struct npc_anub_ar_skirmisherAI : public ScriptedAI { - uiChargeTimer = 11*IN_MILLISECONDS; - uiBackstabTimer = 7*IN_MILLISECONDS; - } + npc_anub_ar_skirmisherAI(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void Reset() OVERRIDE + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) OVERRIDE + { + events.ScheduleEvent(EVENT_ANUBAR_CHARGE, 11000); + events.ScheduleEvent(EVENT_BACKSTAB, 7000); + } - if (uiChargeTimer <= diff) + void UpdateAI(uint32 diff) OVERRIDE { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - DoResetThreat(); - me->AddThreat(target, 1.0f); - DoCast(target, SPELL_CHARGE, true); + switch (eventId) + { + case EVENT_ANUBAR_CHARGE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoResetThreat(); + me->AddThreat(target, 1.0f); + DoCast(target, SPELL_CHARGE, true); + } + events.ScheduleEvent(EVENT_ANUBAR_CHARGE, 15000); + break; + case EVENT_BACKSTAB: + DoCastVictim(SPELL_BACKSTAB); + events.ScheduleEvent(EVENT_BACKSTAB, 12000); + break; + default: + break; + } } - uiChargeTimer = 15*IN_MILLISECONDS; - } else uiChargeTimer -= diff; - if (uiBackstabTimer <= diff) - { - DoCastVictim(SPELL_BACKSTAB); - uiBackstabTimer = 12*IN_MILLISECONDS; - } else uiBackstabTimer -= diff; + DoMeleeAttackIfReady(); + } - DoMeleeAttackIfReady(); + private: + EventMap events; + }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetAzjolNerubAI<npc_anub_ar_skirmisherAI>(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_anub_ar_skirmisherAI(creature); - } }; class npc_anub_ar_shadowcaster : public CreatureScript { -public: - npc_anub_ar_shadowcaster() : CreatureScript("npc_anub_ar_shadowcaster") { } - - struct npc_anub_ar_shadowcasterAI : public ScriptedAI - { - npc_anub_ar_shadowcasterAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 uiShadowBoltTimer; - uint32 uiShadowNovaTimer; + public: + npc_anub_ar_shadowcaster() : CreatureScript("npc_anub_ar_shadowcaster") { } - void Reset() OVERRIDE + struct npc_anub_ar_shadowcasterAI : public ScriptedAI { - uiShadowBoltTimer = 6*IN_MILLISECONDS; - uiShadowNovaTimer = 15*IN_MILLISECONDS; - } + npc_anub_ar_shadowcasterAI(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void Reset() OVERRIDE + { + events.Reset(); + } - if (uiShadowBoltTimer <= diff) + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_SHADOW_BOLT, true); - uiShadowBoltTimer = 15*IN_MILLISECONDS; - } else uiShadowBoltTimer -= diff; + events.ScheduleEvent(EVENT_SHADOW_BOLT, 6000); + events.ScheduleEvent(EVENT_SHADOW_NOVA, 15000); + } - if (uiShadowNovaTimer <= diff) + void UpdateAI(uint32 diff) OVERRIDE { - DoCastVictim(SPELL_SHADOW_NOVA, true); - uiShadowNovaTimer = 17*IN_MILLISECONDS; - } else uiShadowNovaTimer -= diff; + if (!UpdateVictim()) + return; - DoMeleeAttackIfReady(); - } - }; + events.Update(diff); - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_anub_ar_shadowcasterAI(creature); - } -}; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; -class npc_anub_ar_warrior : public CreatureScript -{ -public: - npc_anub_ar_warrior() : CreatureScript("npc_anub_ar_warrior") { } + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHADOW_BOLT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_SHADOW_BOLT, true); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + break; + case EVENT_SHADOW_NOVA: + DoCastVictim(SPELL_SHADOW_NOVA, true); + events.ScheduleEvent(EVENT_SHADOW_NOVA, 17000); + break; + default: + break; + } + } - struct npc_anub_ar_warriorAI : public ScriptedAI - { - npc_anub_ar_warriorAI(Creature* creature) : ScriptedAI(creature){ } + DoMeleeAttackIfReady(); + } - uint32 uiCleaveTimer; - uint32 uiStrikeTimer; + private: + EventMap events; + }; - void Reset() OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - uiCleaveTimer = 11*IN_MILLISECONDS; - uiStrikeTimer = 6*IN_MILLISECONDS; + return GetAzjolNerubAI<npc_anub_ar_shadowcasterAI>(creature); } +}; + +class npc_anub_ar_warrior : public CreatureScript +{ + public: + npc_anub_ar_warrior() : CreatureScript("npc_anub_ar_warrior") { } - void UpdateAI(uint32 diff) OVERRIDE + struct npc_anub_ar_warriorAI : public ScriptedAI { - if (!UpdateVictim()) - return; + npc_anub_ar_warriorAI(Creature* creature) : ScriptedAI(creature) { } - if (uiStrikeTimer <= diff) + void Reset() OVERRIDE { - DoCastVictim(SPELL_STRIKE, true); - uiStrikeTimer = 15*IN_MILLISECONDS; - } else uiStrikeTimer -= diff; + events.Reset(); + } - if (uiCleaveTimer <= diff) + void EnterCombat(Unit* /*who*/) OVERRIDE { - DoCastVictim(SPELL_CLEAVE, true); - uiCleaveTimer = 17*IN_MILLISECONDS; - } else uiCleaveTimer -= diff; + events.ScheduleEvent(EVENT_CLEAVE, 11000); + events.ScheduleEvent(EVENT_STRIKE, 6000); + } - DoMeleeAttackIfReady(); - } - }; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_anub_ar_warriorAI(creature); - } -}; + events.Update(diff); -class npc_watcher_gashra : public CreatureScript -{ -public: - npc_watcher_gashra() : CreatureScript("npc_watcher_gashra") { } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - struct npc_watcher_gashraAI : public ScriptedAI - { - npc_watcher_gashraAI(Creature* creature) : ScriptedAI(creature) { } + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CLEAVE: + DoCastVictim(SPELL_STRIKE, true); + events.ScheduleEvent(EVENT_CLEAVE, 15000); + break; + case EVENT_STRIKE: + DoCastVictim(SPELL_CLEAVE, true); + events.ScheduleEvent(EVENT_STRIKE, 17000); + break; + default: + break; + } + } - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; + DoMeleeAttackIfReady(); + } - void Reset() OVERRIDE - { - uiWebWrapTimer = 11*IN_MILLISECONDS; - uiInfectedBiteTimer = 4*IN_MILLISECONDS; - } + private: + EventMap events; + }; - void EnterCombat(Unit* /*who*/) OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - DoCast(me, SPELL_ENRAGE, true); + return GetAzjolNerubAI<npc_anub_ar_warriorAI>(creature); } +}; + +class npc_watcher_gashra : public CreatureScript +{ + public: + npc_watcher_gashra() : CreatureScript("npc_watcher_gashra") { } - void UpdateAI(uint32 diff) OVERRIDE + struct npc_watcher_gashraAI : public ScriptedAI { - if (!UpdateVictim()) - return; + npc_watcher_gashraAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } - if (uiWebWrapTimer <= diff) + void Reset() OVERRIDE { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 17*IN_MILLISECONDS; - } else uiWebWrapTimer -= diff; + _events.Reset(); + } - if (uiInfectedBiteTimer <= diff) + void EnterCombat(Unit* /*who*/) OVERRIDE + { + DoCast(me, SPELL_ENRAGE, true); + _events.ScheduleEvent(EVENT_WEB_WRAP_GASHRA, 11000); + _events.ScheduleEvent(EVENT_INFECTED_BITE_GASHRA, 4000); + } + + void JustDied(Unit* /*killer*/) OVERRIDE { - DoCastVictim(SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILLISECONDS; - } else uiInfectedBiteTimer -= diff; + Creature* krikthir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KRIKTHIR_THE_GATEWATCHER)); + if (krikthir && krikthir->IsAlive()) + krikthir->AI()->Talk(SAY_PREFIGHT); + } - DoMeleeAttackIfReady(); - } - }; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_watcher_gashraAI(creature); - } -}; + _events.Update(diff); -class npc_watcher_narjil : public CreatureScript -{ -public: - npc_watcher_narjil() : CreatureScript("npc_watcher_narjil") { } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - struct npc_watcher_narjilAI : public ScriptedAI - { - npc_watcher_narjilAI(Creature* creature) : ScriptedAI(creature) { } + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_WEB_WRAP_GASHRA: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_WEB_WRAP, true); + _events.ScheduleEvent(EVENT_WEB_WRAP_GASHRA, 17000); + break; + case EVENT_INFECTED_BITE_GASHRA: + DoCastVictim(SPELL_INFECTED_BITE, true); + _events.ScheduleEvent(EVENT_INFECTED_BITE_GASHRA, 15000); + break; + default: + break; + } + } - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiBindingWebsTimer; + DoMeleeAttackIfReady(); + } - void Reset() OVERRIDE + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - uiWebWrapTimer = 11*IN_MILLISECONDS; - uiInfectedBiteTimer = 4*IN_MILLISECONDS; - uiBindingWebsTimer = 17*IN_MILLISECONDS; + return GetAzjolNerubAI<npc_watcher_gashraAI>(creature); } +}; + +class npc_watcher_narjil : public CreatureScript +{ + public: + npc_watcher_narjil() : CreatureScript("npc_watcher_narjil") { } - void UpdateAI(uint32 diff) OVERRIDE + struct npc_watcher_narjilAI : public ScriptedAI { - if (!UpdateVictim()) - return; + npc_watcher_narjilAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } - if (uiWebWrapTimer <= diff) + void Reset() OVERRIDE { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 15*IN_MILLISECONDS; - } else uiWebWrapTimer -= diff; + _events.Reset(); + } - if (uiInfectedBiteTimer <= diff) + void EnterCombat(Unit* /*who*/) OVERRIDE { - DoCastVictim(SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 11*IN_MILLISECONDS; - } else uiInfectedBiteTimer -= diff; + _events.ScheduleEvent(EVENT_WEB_WRAP_NARJIL, 11000); + _events.ScheduleEvent(EVENT_INFECTED_BITE_NARJIL, 4000); + _events.ScheduleEvent(EVENT_BINDING_WEBS, 17000); + } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + Creature* krikthir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KRIKTHIR_THE_GATEWATCHER)); + if (krikthir && krikthir->IsAlive()) + krikthir->AI()->Talk(SAY_PREFIGHT); + } - if (uiBindingWebsTimer <= diff) + void UpdateAI(uint32 diff) OVERRIDE { - DoCastVictim(SPELL_BLINDING_WEBS, true); - uiBindingWebsTimer = 17*IN_MILLISECONDS; - } else uiBindingWebsTimer -= diff; + if (!UpdateVictim()) + return; - DoMeleeAttackIfReady(); - } - }; + _events.Update(diff); - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_watcher_narjilAI(creature); - } -}; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; -class npc_watcher_silthik : public CreatureScript -{ -public: - npc_watcher_silthik() : CreatureScript("npc_watcher_silthik") { } + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_WEB_WRAP_NARJIL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_WEB_WRAP, true); + _events.ScheduleEvent(EVENT_WEB_WRAP_NARJIL, 15000); + break; + case EVENT_INFECTED_BITE_NARJIL: + DoCastVictim(SPELL_INFECTED_BITE, true); + _events.ScheduleEvent(EVENT_INFECTED_BITE_NARJIL, 11000); + break; + case EVENT_BINDING_WEBS: + DoCastVictim(SPELL_BLINDING_WEBS, true); + _events.ScheduleEvent(EVENT_BINDING_WEBS, 17000); + break; + default: + break; + } + } - struct npc_watcher_silthikAI : public ScriptedAI - { - npc_watcher_silthikAI(Creature* creature) : ScriptedAI(creature) { } + DoMeleeAttackIfReady(); + } - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiPoisonSprayTimer; + private: + EventMap _events; + InstanceScript* _instance; + }; - void Reset() OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - uiWebWrapTimer = 11*IN_MILLISECONDS; - uiInfectedBiteTimer = 4*IN_MILLISECONDS; - uiPoisonSprayTimer = 15*IN_MILLISECONDS; + return GetAzjolNerubAI<npc_watcher_narjilAI>(creature); } +}; + +class npc_watcher_silthik : public CreatureScript +{ + public: + npc_watcher_silthik() : CreatureScript("npc_watcher_silthik") { } - void UpdateAI(uint32 diff) OVERRIDE + struct npc_watcher_silthikAI : public ScriptedAI { - if (!UpdateVictim()) - return; + npc_watcher_silthikAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } - if (uiWebWrapTimer <= diff) + void Reset() OVERRIDE { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_WEB_WRAP, true); + _events.Reset(); + } - uiWebWrapTimer = 15*IN_MILLISECONDS; - } else uiWebWrapTimer -= diff; + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _events.ScheduleEvent(EVENT_WEB_WRAP_SILTHIK, 11000); + _events.ScheduleEvent(EVENT_INFECTED_BITE_SILTHIK, 4000); + _events.ScheduleEvent(EVENT_POISON_SPRAY, 15000); + } - if (uiInfectedBiteTimer <= diff) + void JustDied(Unit* /*killer*/) OVERRIDE { - DoCastVictim(SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILLISECONDS; - } else uiInfectedBiteTimer -= diff; + Creature* krikthir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KRIKTHIR_THE_GATEWATCHER)); + if (krikthir && krikthir->IsAlive()) + krikthir->AI()->Talk(SAY_PREFIGHT); + } - if (uiPoisonSprayTimer <= diff) + void UpdateAI(uint32 diff) OVERRIDE { - DoCastVictim(SPELL_POSION_SPRAY, true); - uiPoisonSprayTimer = 17*IN_MILLISECONDS; - } else uiPoisonSprayTimer -= diff; + if (!UpdateVictim()) + return; + + _events.Update(diff); - DoMeleeAttackIfReady(); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - } - }; + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_WEB_WRAP_SILTHIK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_WEB_WRAP, true); + _events.ScheduleEvent(EVENT_WEB_WRAP_SILTHIK, 15000); + break; + case EVENT_INFECTED_BITE_SILTHIK: + DoCastVictim(SPELL_INFECTED_BITE, true); + _events.ScheduleEvent(EVENT_INFECTED_BITE_SILTHIK, 11000); + break; + case EVENT_POISON_SPRAY: + DoCastVictim(SPELL_POSION_SPRAY, true); + _events.ScheduleEvent(EVENT_POISON_SPRAY, 17000); + break; + default: + break; + } + } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_watcher_silthikAI(creature); - } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetAzjolNerubAI<npc_watcher_silthikAI>(creature); + } }; class achievement_watch_him_die : public AchievementCriteriaScript diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index 42a7ee15bb6..aff3c0a9528 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -168,6 +168,7 @@ set(scripts_STAT_SRCS Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp + Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp Northrend/IcecrownCitadel/boss_festergut.cpp Northrend/IcecrownCitadel/boss_rotface.cpp diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp index 9ae6f811e19..a24cd4db7c5 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp @@ -73,7 +73,7 @@ enum Enums //Whelps NPC_TWILIGHT_WHELP = 30890, - NPC_SHARTHARION_TWILIGHT_WHELP = 31214, + NPC_SARTHARION_TWILIGHT_WHELP = 31214, SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s //flame tsunami @@ -253,7 +253,7 @@ struct dummy_dragonAI : public ScriptedAI { case NPC_TENEBRON: { - if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) + if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) { for (uint32 i = 0; i < 6; ++i) me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); @@ -267,7 +267,7 @@ struct dummy_dragonAI : public ScriptedAI } case NPC_SHADRON: { - if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) + if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000); else me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000); @@ -276,7 +276,7 @@ struct dummy_dragonAI : public ScriptedAI } case NPC_VESPERON: { - if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) + if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) { if (Creature* acolyte = me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000)) { @@ -816,10 +816,10 @@ public: { me->RemoveAllAuras(); - if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) + if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); else - me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + me->SummonCreature(NPC_SARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); me->DealDamage(me, me->GetHealth()); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp index a60e69d6479..8b6cbb340e5 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp @@ -357,7 +357,7 @@ public: if (instance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && instance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED) { if (instance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) - me->AI()->SetData(DATA_START, 0); + SetData(DATA_START, 0); if (instance->GetData(BOSS_GRAND_CHAMPIONS) == DONE) DoStartArgentChampionEncounter(); @@ -452,7 +452,7 @@ public: case VEHICLE_ORGRIMMAR_WOLF: case VEHICLE_SILVERMOON_HAWKSTRIDER: case VEHICLE_DARKSPEAR_RAPTOR: - me->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED, 0); + SetData(DATA_LESSER_CHAMPIONS_DEFEATED, 0); break; } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index ea166585bb3..4210ebfcad5 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -294,6 +294,8 @@ class npc_snobold_vassal : public CreatureScript { npc_snobold_vassalAI(Creature* creature) : ScriptedAI(creature) { + _targetGUID = 0; + _targetDied = false; _instance = creature->GetInstanceScript(); _instance->SetData(DATA_SNOBOLD_COUNT, INCREASE); } diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp index 09db3f89c26..f84f288d55a 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -231,7 +231,7 @@ public: if (Creature* crystalChannelTarget = crystal->FindNearestCreature(NPC_CRYSTAL_CHANNEL_TARGET, 5.0f)) { if (active) - crystalChannelTarget->AI()->DoCastAOE(SPELL_BEAM_CHANNEL); + crystalChannelTarget->CastSpell((Unit*)NULL, SPELL_BEAM_CHANNEL); else if (crystalChannelTarget->HasUnitState(UNIT_STATE_CASTING)) crystalChannelTarget->CastStop(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 1f4713415ac..af459729eb8 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -891,7 +891,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID)) { lichking->AI()->Talk(SAY_LK_ESCAPE_3); - lichking->AI()->DoCast(me, SPELL_RAISE_DEAD); + lichking->CastSpell(me, SPELL_RAISE_DEAD); lichking->Attack(me, true); } _events.ScheduleEvent(EVENT_ESCAPE_13, 4000); @@ -899,15 +899,15 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript case EVENT_ESCAPE_13: if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID)) { - lichking->AI()->DoCast(lichking, SPELL_REMORSELESS_WINTER, true); - lichking->AI()->DoCast(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); + lichking->CastSpell(lichking, SPELL_REMORSELESS_WINTER, true); + lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); lichking->GetMotionMaster()->MoveIdle(); lichking->GetMotionMaster()->MoveChase(me); } if (Creature* walltarget = me->SummonCreature(NPC_ICE_WALL, IceWalls[0], TEMPSUMMON_MANUAL_DESPAWN, 720000)) { _walltargetGUID = walltarget->GetGUID(); - walltarget->AI()->DoCast(walltarget, SPELL_SUMMON_ICE_WALL); + walltarget->CastSpell(walltarget, SPELL_SUMMON_ICE_WALL); walltarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); me->Attack(walltarget, false); } @@ -948,7 +948,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript { lichking->StopMoving(); lichking->AI()->Talk(SAY_LK_ESCAPE_3); - lichking->AI()->DoCast(me, SPELL_RAISE_DEAD); + lichking->CastSpell(me, SPELL_RAISE_DEAD); } DestroyIceWall(); @@ -969,7 +969,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID)) { if (_icewall && _icewall < 4) - lichking->AI()->DoCast(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); + lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); lichking->GetMotionMaster()->MoveIdle(); lichking->GetMotionMaster()->MoveChase(me); lichking->SetReactState(REACT_PASSIVE); @@ -980,7 +980,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript if (Creature* walltarget = me->SummonCreature(NPC_ICE_WALL, IceWalls[_icewall], TEMPSUMMON_MANUAL_DESPAWN, 720000)) { _walltargetGUID = walltarget->GetGUID(); - walltarget->AI()->DoCast(walltarget, SPELL_SUMMON_ICE_WALL); + walltarget->CastSpell(walltarget, SPELL_SUMMON_ICE_WALL); walltarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); me->Attack(walltarget, false); } @@ -1018,9 +1018,9 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID)) { if (_icewall && _icewall < 3) - lichking->AI()->DoCast(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); + lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); else - lichking->AI()->DoCast(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION); + lichking->CastSpell(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION); } if (_icewall == 3) _events.ScheduleEvent(EVENT_ESCAPE_21, 16000); // last wall, really far @@ -1036,10 +1036,10 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID)) { if (_icewall == 1) - lichking->AI()->DoCast(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION); + lichking->CastSpell(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION); else if (_icewall > 1 && _icewall < 4) { - lichking->AI()->DoCast(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); + lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR); _events.ScheduleEvent(EVENT_ESCAPE_22, 1000); } } @@ -1048,7 +1048,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID)) { if (_icewall >= 2 && _icewall < 4) - lichking->AI()->DoCast(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION); + lichking->CastSpell(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION); } break; case EVENT_ESCAPE_23: // FINAL PART @@ -1180,7 +1180,10 @@ enum TrashEvents struct npc_gauntlet_trash : public ScriptedAI { - npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + { + InternalWaveId = 0; + } void Reset() OVERRIDE { diff --git a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp index dd1d35e639e..0feec20d55f 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp @@ -219,7 +219,10 @@ public: struct npc_slad_ran_constrictorAI : public ScriptedAI { - npc_slad_ran_constrictorAI(Creature* creature) : ScriptedAI(creature) { } + npc_slad_ran_constrictorAI(Creature* creature) : ScriptedAI(creature) + { + uiGripOfSladRanTimer = 1 * IN_MILLISECONDS; + } uint32 uiGripOfSladRanTimer; @@ -247,8 +250,9 @@ public: target->CastSpell(target, SPELL_SNAKE_WRAP, true); if (TempSummon* _me = me->ToTempSummon()) - if (Creature* sladran = _me->GetSummoner()->ToCreature()) - sladran->AI()->SetGUID(target->GetGUID(), DATA_SNAKES_WHYD_IT_HAVE_TO_BE_SNAKES); + if (Unit* summoner = _me->GetSummoner()) + if (Creature* sladran = summoner->ToCreature()) + sladran->AI()->SetGUID(target->GetGUID(), DATA_SNAKES_WHYD_IT_HAVE_TO_BE_SNAKES); me->DespawnOrUnsummon(); } @@ -270,7 +274,10 @@ public: struct npc_slad_ran_viperAI : public ScriptedAI { - npc_slad_ran_viperAI(Creature* creature) : ScriptedAI(creature) { } + npc_slad_ran_viperAI(Creature* creature) : ScriptedAI(creature) + { + uiVenomousBiteTimer = 2 * IN_MILLISECONDS; + } uint32 uiVenomousBiteTimer; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 3d4ee279685..bbf3e8afc0f 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -800,7 +800,7 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg : public SpellScriptLoader // this is an additional effect to be executed void PeriodicTick(AuraEffect const* aurEff) { - SpellInfo const* damageSpell = sSpellMgr->GetSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE); + SpellInfo const* damageSpell = sSpellMgr->EnsureSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE); int32 damage = damageSpell->Effects[EFFECT_0].CalcValue(); float multiplier = 0.3375f + 0.1f * uint32(aurEff->GetTickNumber()/10); // do not convert to 0.01f - we need tick number/10 as INT (damage increases every 10 ticks) damage = int32(damage * multiplier); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 7be766c0a0e..e8048404027 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -333,6 +333,7 @@ class boss_deathbringer_saurfang : public CreatureScript void JustReachedHome() OVERRIDE { _JustReachedHome(); + Reset(); instance->SetBossState(DATA_DEATHBRINGER_SAURFANG, FAIL); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MARK_OF_THE_FALLEN_CHAMPION); } @@ -376,7 +377,16 @@ class boss_deathbringer_saurfang : public CreatureScript void JustSummoned(Creature* summon) OVERRIDE { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) + { + if (target->GetTransport()) + { + summon->DespawnOrUnsummon(1); + EnterEvadeMode(); + return; + } + summon->AI()->AttackStart(target); + } summon->CastSpell(summon, SPELL_BLOOD_LINK_BEAST, true); summon->CastSpell(summon, SPELL_RESISTANT_SKIN, true); @@ -399,6 +409,12 @@ class boss_deathbringer_saurfang : public CreatureScript void SpellHitTarget(Unit* target, SpellInfo const* spell) OVERRIDE { + if (target->GetTransport()) + { + EnterEvadeMode(); + return; + } + switch (spell->Id) { case SPELL_MARK_OF_THE_FALLEN_CHAMPION: @@ -571,6 +587,14 @@ class boss_deathbringer_saurfang : public CreatureScript } } + bool CanAIAttack(Unit const* target) const OVERRIDE + { + if (target->GetTransport()) + return false; + + return true; + } + static uint32 const FightWonValue; private: diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp new file mode 100644 index 00000000000..0a9e207db36 --- /dev/null +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -0,0 +1,2484 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CellImpl.h" +#include "CreatureTextMgr.h" +#include "GridNotifiersImpl.h" +#include "GossipDef.h" +#include "MoveSpline.h" +#include "MoveSplineInit.h" +#include "PassiveAI.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" +#include "Transport.h" +#include "TransportMgr.h" +#include "Vehicle.h" +#include "icecrown_citadel.h" + +enum Texts +{ + // High Overlord Saurfang + SAY_SAURFANG_INTRO_1 = 0, + SAY_SAURFANG_INTRO_2 = 1, + SAY_SAURFANG_INTRO_3 = 2, + SAY_SAURFANG_INTRO_4 = 3, + SAY_SAURFANG_INTRO_5 = 4, + SAY_SAURFANG_INTRO_6 = 5, + SAY_SAURFANG_INTRO_A = 6, + SAY_SAURFANG_BOARD = 7, + SAY_SAURFANG_ENTER_SKYBREAKER = 8, + SAY_SAURFANG_AXETHROWERS = 9, + SAY_SAURFANG_ROCKETEERS = 10, + SAY_SAURFANG_MAGES = 11, + SAY_SAURFANG_VICTORY = 12, + SAY_SAURFANG_WIPE = 13, + + // Muradin Bronzebeard + SAY_MURADIN_INTRO_1 = 0, + SAY_MURADIN_INTRO_2 = 1, + SAY_MURADIN_INTRO_3 = 2, + SAY_MURADIN_INTRO_4 = 3, + SAY_MURADIN_INTRO_5 = 4, + SAY_MURADIN_INTRO_6 = 5, + SAY_MURADIN_INTRO_7 = 6, + SAY_MURADIN_INTRO_H = 7, + SAY_MURADIN_BOARD = 8, + SAY_MURADIN_ENTER_ORGRIMMS_HAMMER = 9, + SAY_MURADIN_RIFLEMAN = 10, + SAY_MURADIN_MORTAR = 11, + SAY_MURADIN_SORCERERS = 12, + SAY_MURADIN_VICTORY = 13, + SAY_MURADIN_WIPE = 14, + + SAY_ZAFOD_ROCKET_PACK_ACTIVE = 0, + SAY_ZAFOD_ROCKET_PACK_DISABLED = 1, + + SAY_OVERHEAT = 0 +}; + +enum Events +{ + // High Overlord Saurfang + EVENT_INTRO_H_1 = 1, + EVENT_INTRO_H_2 = 2, + EVENT_INTRO_SUMMON_SKYBREAKER = 3, + EVENT_INTRO_H_3 = 4, + EVENT_INTRO_H_4 = 5, + EVENT_INTRO_H_5 = 6, + EVENT_INTRO_H_6 = 7, + + // Muradin Bronzebeard + EVENT_INTRO_A_1 = 1, + EVENT_INTRO_A_2 = 2, + EVENT_INTRO_SUMMON_ORGRIMS_HAMMER = 3, + EVENT_INTRO_A_3 = 4, + EVENT_INTRO_A_4 = 5, + EVENT_INTRO_A_5 = 6, + EVENT_INTRO_A_6 = 7, + EVENT_INTRO_A_7 = 8, + + EVENT_KEEP_PLAYER_IN_COMBAT = 9, + EVENT_SUMMON_MAGE = 10, + EVENT_ADDS = 11, + EVENT_ADDS_BOARD_YELL = 12, + EVENT_CHECK_RIFLEMAN = 13, + EVENT_CHECK_MORTAR = 14, + EVENT_CLEAVE = 15, + + EVENT_BLADESTORM = 16, + EVENT_WOUNDING_STRIKE = 17 +}; + +enum Spells +{ + // Applied on friendly transport NPCs + SPELL_FRIENDLY_BOSS_DAMAGE_MOD = 70339, + SPELL_CHECK_FOR_PLAYERS = 70332, + SPELL_GUNSHIP_FALL_TELEPORT = 67335, + SPELL_TELEPORT_PLAYERS_ON_RESET_A = 70446, + SPELL_TELEPORT_PLAYERS_ON_RESET_H = 71284, + SPELL_TELEPORT_PLAYERS_ON_VICTORY = 72340, + SPELL_ACHIEVEMENT = 72959, + SPELL_AWARD_REPUTATION_BOSS_KILL = 73843, + + // Murading Bronzebeard + // High Overlord Saurfang + SPELL_BATTLE_FURY = 69637, + SPELL_RENDING_THROW = 70309, + SPELL_CLEAVE = 15284, + SPELL_TASTE_OF_BLOOD = 69634, + + // Applied on enemy NPCs + SPELL_MELEE_TARGETING_ON_SKYBREAKER = 70219, + SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER = 70294, + + // Gunship Hull + SPELL_EXPLOSION_WIPE = 72134, + SPELL_EXPLOSION_VICTORY = 72137, + + // Hostile NPCs + SPELL_TELEPORT_TO_ENEMY_SHIP = 70104, + SPELL_BATTLE_EXPERIENCE = 71201, + SPELL_EXPERIENCED = 71188, + SPELL_VETERAN = 71193, + SPELL_ELITE = 71195, + SPELL_ADDS_BERSERK = 72525, + + // Skybreaker Sorcerer + // Kor'kron Battle-Mage + SPELL_SHADOW_CHANNELING = 43897, + SPELL_BELOW_ZERO = 69705, + + // Skybreaker Rifleman + // Kor'kron Axethrower + SPELL_SHOOT = 70162, + SPELL_HURL_AXE = 70161, + SPELL_BURNING_PITCH_A = 70403, + SPELL_BURNING_PITCH_H = 70397, + SPELL_BURNING_PITCH = 69660, + + // Skybreaker Mortar Soldier + // Kor'kron Rocketeer + SPELL_ROCKET_ARTILLERY_A = 70609, + SPELL_ROCKET_ARTILLERY_H = 69678, + SPELL_BURNING_PITCH_DAMAGE_A = 70383, + SPELL_BURNING_PITCH_DAMAGE_H = 70374, + + // Skybreaker Marine + // Kor'kron Reaver + SPELL_DESPERATE_RESOLVE = 69647, + + // Skybreaker Sergeant + // Kor'kron Sergeant + SPELL_BLADESTORM = 69652, + SPELL_WOUNDING_STRIKE = 69651, + + // + SPELL_LOCK_PLAYERS_AND_TAP_CHEST = 72347, + SPELL_ON_SKYBREAKER_DECK = 70120, + SPELL_ON_ORGRIMS_HAMMER_DECK = 70121, + + // Rocket Pack + SPELL_ROCKET_PACK_DAMAGE = 69193, + SPELL_ROCKET_BURST = 69192, + SPELL_ROCKET_PACK_USEABLE = 70348, + + // Alliance Gunship Cannon + // Horde Gunship Cannon + SPELL_OVERHEAT = 69487, + SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO = 68576, + SPELL_EJECT_ALL_PASSENGERS_WIPE = 50630 +}; + +enum MiscData +{ + ITEM_GOBLIN_ROCKET_PACK = 49278, + + PHASE_COMBAT = 0, + PHASE_INTRO = 1, + + MUSIC_ENCOUNTER = 17289 +}; + +enum EncounterActions +{ + ACTION_SPAWN_MAGE = 1, + ACTION_SPAWN_ALL_ADDS = 2, + ACTION_CLEAR_SLOT = 3, + ACTION_SET_SLOT = 4, + ACTION_SHIP_VISITS = 5 +}; + +Position const SkybreakerAddsSpawnPos = { 15.91131f, 0.0f, 20.4628f, M_PI }; +Position const OrgrimsHammerAddsSpawnPos = { 60.728395f, 0.0f, 38.93467f, M_PI }; + +// Horde encounter +Position const SkybreakerTeleportPortal = { 6.666975f, 0.013001f, 20.87888f, 0.0f }; +Position const OrgrimsHammerTeleportExit = { 7.461699f, 0.158853f, 35.72989f, 0.0f }; + +// Alliance encounter +Position const OrgrimsHammerTeleportPortal = { 47.550990f, -0.101778f, 37.61111f, 0.0f }; +Position const SkybreakerTeleportExit = { -17.55738f, -0.090421f, 21.18366f, 0.0f }; + +uint32 const MuradinExitPathSize = 10; +G3D::Vector3 const MuradinExitPath[MuradinExitPathSize] = +{ + { 8.130936f, -0.2699585f, 20.31728f }, + { 6.380936f, -0.2699585f, 20.31728f }, + { 3.507703f, 0.02986573f, 20.78463f }, + { -2.767633f, 3.743143f, 20.37663f }, + { -4.017633f, 4.493143f, 20.12663f }, + { -7.242224f, 6.856013f, 20.03468f }, + { -7.742224f, 8.606013f, 20.78468f }, + { -7.992224f, 9.856013f, 21.28468f }, + { -12.24222f, 23.10601f, 21.28468f }, + { -14.88477f, 25.20844f, 21.59985f }, +}; + +uint32 const SaurfangExitPathSize = 13; +G3D::Vector3 const SaurfangExitPath[SaurfangExitPathSize] = +{ + { 30.43987f, 0.1475817f, 36.10674f }, + { 21.36141f, -3.056458f, 35.42970f }, + { 19.11141f, -3.806458f, 35.42970f }, + { 19.01736f, -3.299440f, 35.39428f }, + { 18.6747f, -5.862823f, 35.66611f }, + { 18.6747f, -7.862823f, 35.66611f }, + { 18.1747f, -17.36282f, 35.66611f }, + { 18.1747f, -22.61282f, 35.66611f }, + { 17.9247f, -24.36282f, 35.41611f }, + { 17.9247f, -26.61282f, 35.66611f }, + { 17.9247f, -27.86282f, 35.66611f }, + { 17.9247f, -29.36282f, 35.66611f }, + { 15.33203f, -30.42621f, 35.93796f } +}; + +enum PassengerSlots +{ + // Freezing the cannons + SLOT_FREEZE_MAGE = 0, + + // Channeling the portal, refilled with adds that board player's ship + SLOT_MAGE_1 = 1, + SLOT_MAGE_2 = 2, + + // Rifleman + SLOT_RIFLEMAN_1 = 3, + SLOT_RIFLEMAN_2 = 4, + SLOT_RIFLEMAN_3 = 5, + SLOT_RIFLEMAN_4 = 6, + + // Additional Rifleman on 25 man + SLOT_RIFLEMAN_5 = 7, + SLOT_RIFLEMAN_6 = 8, + SLOT_RIFLEMAN_7 = 9, + SLOT_RIFLEMAN_8 = 10, + + // Mortar + SLOT_MORTAR_1 = 11, + SLOT_MORTAR_2 = 12, + + // Additional spawns on 25 man + SLOT_MORTAR_3 = 13, + SLOT_MORTAR_4 = 14, + + // Marines + SLOT_MARINE_1 = 15, + SLOT_MARINE_2 = 16, + + // Additional spawns on 25 man + SLOT_MARINE_3 = 17, + SLOT_MARINE_4 = 18, + + // Sergeants + SLOT_SERGEANT_1 = 19, + + // Additional spawns on 25 man + SLOT_SERGEANT_2 = 20, + + MAX_SLOTS +}; + +struct SlotInfo +{ + uint32 Entry; + Position TargetPosition; + uint32 Cooldown; +}; + +SlotInfo const SkybreakerSlotInfo[MAX_SLOTS] = +{ + { NPC_SKYBREAKER_SORCERER, { -9.479858f, 0.05663967f, 20.77026f, 4.729842f }, 0 }, + + { NPC_SKYBREAKER_SORCERER, { 6.385986f, 4.978760f, 20.55417f, 4.694936f }, 0 }, + { NPC_SKYBREAKER_SORCERER, { 6.579102f, -4.674561f, 20.55060f, 1.553343f }, 0 }, + + { NPC_SKYBREAKER_RIFLEMAN, { -29.563900f, -17.95801f, 20.73837f, 4.747295f }, 30 }, + { NPC_SKYBREAKER_RIFLEMAN, { -18.017210f, -18.82056f, 20.79150f, 4.747295f }, 30 }, + { NPC_SKYBREAKER_RIFLEMAN, { -9.1193850f, -18.79102f, 20.58887f, 4.712389f }, 30 }, + { NPC_SKYBREAKER_RIFLEMAN, { -0.3364258f, -18.87183f, 20.56824f, 4.712389f }, 30 }, + + { NPC_SKYBREAKER_RIFLEMAN, { -34.705810f, -17.67261f, 20.51523f, 4.729842f }, 30 }, + { NPC_SKYBREAKER_RIFLEMAN, { -23.562010f, -18.28564f, 20.67859f, 4.729842f }, 30 }, + { NPC_SKYBREAKER_RIFLEMAN, { -13.602780f, -18.74268f, 20.59622f, 4.712389f }, 30 }, + { NPC_SKYBREAKER_RIFLEMAN, { -4.3350220f, -18.84619f, 20.58234f, 4.712389f }, 30 }, + + { NPC_SKYBREAKER_MORTAR_SOLDIER, { -31.70142f, 18.02783f, 20.77197f, 4.712389f }, 30 }, + { NPC_SKYBREAKER_MORTAR_SOLDIER, { -9.368652f, 18.75806f, 20.65335f, 4.712389f }, 30 }, + + { NPC_SKYBREAKER_MORTAR_SOLDIER, { -20.40851f, 18.40381f, 20.50647f, 4.694936f }, 30 }, + { NPC_SKYBREAKER_MORTAR_SOLDIER, { 0.1585693f, 18.11523f, 20.41949f, 4.729842f }, 30 }, + + { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 }, + { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 }, + + { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 }, + { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 }, + + { NPC_SKYBREAKER_SERGEANT, SkybreakerTeleportPortal, 0 }, + + { NPC_SKYBREAKER_SERGEANT, SkybreakerTeleportPortal, 0 } +}; + +SlotInfo const OrgrimsHammerSlotInfo[MAX_SLOTS] = +{ + { NPC_KOR_KRON_BATTLE_MAGE, { 13.58548f, 0.3867192f, 34.99243f, 1.53589f }, 0 }, + + { NPC_KOR_KRON_BATTLE_MAGE, { 47.29290f, -4.308941f, 37.55550f, 1.570796f }, 0 }, + { NPC_KOR_KRON_BATTLE_MAGE, { 47.34621f, 4.032004f, 37.70952f, 4.817109f }, 0 }, + + { NPC_KOR_KRON_AXETHROWER, { -12.09280f, 27.65942f, 33.58557f, 1.53589f }, 30 }, + { NPC_KOR_KRON_AXETHROWER, { -3.170555f, 28.30652f, 34.21082f, 1.53589f }, 30 }, + { NPC_KOR_KRON_AXETHROWER, { 14.928040f, 26.18018f, 35.47803f, 1.53589f }, 30 }, + { NPC_KOR_KRON_AXETHROWER, { 24.703310f, 25.36584f, 35.97845f, 1.53589f }, 30 }, + + { NPC_KOR_KRON_AXETHROWER, { -16.65302f, 27.59668f, 33.18726f, 1.53589f }, 30 }, + { NPC_KOR_KRON_AXETHROWER, { -8.084572f, 28.21448f, 33.93805f, 1.53589f }, 30 }, + { NPC_KOR_KRON_AXETHROWER, { 7.594765f, 27.41968f, 35.00775f, 1.53589f }, 30 }, + { NPC_KOR_KRON_AXETHROWER, { 20.763390f, 25.58215f, 35.75287f, 1.53589f }, 30 }, + + { NPC_KOR_KRON_ROCKETEER, { -11.44849f, -25.71838f, 33.64343f, 1.518436f }, 30 }, + { NPC_KOR_KRON_ROCKETEER, { 12.30336f, -25.69653f, 35.32373f, 1.518436f }, 30 }, + + { NPC_KOR_KRON_ROCKETEER, { -0.05931854f, -25.46399f, 34.50592f, 1.518436f }, 30 }, + { NPC_KOR_KRON_ROCKETEER, { 27.62149000f, -23.48108f, 36.12708f, 1.518436f }, 30 }, + + { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 }, + { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 }, + + { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 }, + { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 }, + + { NPC_KOR_KRON_SERGEANT, OrgrimsHammerTeleportPortal, 0 }, + + { NPC_KOR_KRON_SERGEANT, OrgrimsHammerTeleportPortal, 0 } +}; + +class PassengerController +{ +public: + PassengerController() + { + ResetSlots(HORDE); + } + + void SetTransport(Transport* transport) { _transport = transport; } + + void ResetSlots(uint32 team) + { + _transport = NULL; + memset(_controlledSlots, 0, sizeof(uint64)* MAX_SLOTS); + memset(_respawnCooldowns, 0, sizeof(time_t)* MAX_SLOTS); + _spawnPoint = team == HORDE ? &OrgrimsHammerAddsSpawnPos : &SkybreakerAddsSpawnPos; + _slotInfo = team == HORDE ? OrgrimsHammerSlotInfo : SkybreakerSlotInfo; + } + + bool SummonCreatures(PassengerSlots first, PassengerSlots last) + { + if (!_transport) + return false; + + bool summoned = false; + time_t now = time(NULL); + for (int32 i = first; i <= last; ++i) + { + if (_respawnCooldowns[i] > now) + continue; + + if (_controlledSlots[i]) + { + Creature* current = ObjectAccessor::GetCreature(*_transport, _controlledSlots[i]); + if (current && current->IsAlive()) + continue; + } + + if (Creature* passenger = _transport->SummonPassenger(_slotInfo[i].Entry, SelectSpawnPoint(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, NULL, 15000)) + { + _controlledSlots[i] = passenger->GetGUID(); + _respawnCooldowns[i] = time_t(0); + passenger->AI()->SetData(ACTION_SET_SLOT, i); + summoned = true; + } + } + + return summoned; + } + + void ClearSlot(PassengerSlots slot) + { + _controlledSlots[slot] = 0; + _respawnCooldowns[slot] = time(NULL) + _slotInfo[slot].Cooldown; + } + + bool SlotsNeedRefill(PassengerSlots first, PassengerSlots last) const + { + for (int32 i = first; i <= last; ++i) + if (!_controlledSlots[i]) + return true; + + return false; + } + +private: + Position SelectSpawnPoint() const + { + Position newPos; + float angle = frand(-M_PI * 0.5f, M_PI * 0.5f); + newPos.m_positionX = _spawnPoint->GetPositionX() + 2.0f * std::cos(angle); + newPos.m_positionY = _spawnPoint->GetPositionY() + 2.0f * std::sin(angle); + newPos.m_positionZ = _spawnPoint->GetPositionZ(); + newPos.SetOrientation(_spawnPoint->GetOrientation()); + return newPos; + } + + Transport* _transport; + uint64 _controlledSlots[MAX_SLOTS]; + time_t _respawnCooldowns[MAX_SLOTS]; + Position const* _spawnPoint; + SlotInfo const* _slotInfo; +}; + +class DelayedMovementEvent : public BasicEvent +{ +public: + DelayedMovementEvent(Creature* owner, Position const& dest) : _owner(owner), _dest(dest) { } + + bool Execute(uint64, uint32) OVERRIDE + { + if (!_owner->IsAlive()) + return true; + + _owner->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, *_owner, false); + + Movement::MoveSplineInit init(_owner); + init.DisableTransportPathTransformations(); + init.MoveTo(_dest.GetPositionX(), _dest.GetPositionY(), _dest.GetPositionZ(), false); + init.Launch(); + + return true; + } + +private: + Creature* _owner; + Position const& _dest; +}; + +class ResetEncounterEvent : public BasicEvent +{ +public: + ResetEncounterEvent(Unit* caster, uint32 spellId, uint64 otherTransport) : _caster(caster), _spellId(spellId), _otherTransport(otherTransport) { } + + bool Execute(uint64, uint32) OVERRIDE + { + _caster->CastSpell(_caster, _spellId, true); + _caster->GetTransport()->AddObjectToRemoveList(); + + if (GameObject* go = HashMapHolder<GameObject>::Find(_otherTransport)) + go->AddObjectToRemoveList(); + + return true; + } + +private: + Unit* _caster; + uint32 _spellId; + uint64 _otherTransport; +}; + +class BattleExperienceEvent : public BasicEvent +{ +public: + static uint32 const ExperiencedSpells[5]; + static uint32 const ExperiencedTimes[5]; + + BattleExperienceEvent(Creature* creature) : _creature(creature), _level(0) { } + + bool Execute(uint64 timer, uint32 /*diff*/) OVERRIDE + { + if (!_creature->IsAlive()) + return true; + + _creature->RemoveAurasDueToSpell(ExperiencedSpells[_level]); + ++_level; + + _creature->CastSpell(_creature, ExperiencedSpells[_level], TRIGGERED_FULL_MASK); + if (_level < (_creature->GetMap()->IsHeroic() ? 4 : 3)) + { + _creature->m_Events.AddEvent(this, timer + ExperiencedTimes[_level]); + return false; + } + + return true; + } + +private: + Creature* _creature; + int32 _level; +}; + +uint32 const BattleExperienceEvent::ExperiencedSpells[5] = { 0, SPELL_EXPERIENCED, SPELL_VETERAN, SPELL_ELITE, SPELL_ADDS_BERSERK }; +uint32 const BattleExperienceEvent::ExperiencedTimes[5] = { 100000, 70000, 60000, 90000, 0 }; + +struct gunship_npc_AI : public ScriptedAI +{ + gunship_npc_AI(Creature* creature) : ScriptedAI(creature), + Instance(creature->GetInstanceScript()), Slot(NULL), Index(uint32(-1)) + { + BurningPitchId = Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_BURNING_PITCH_A : SPELL_BURNING_PITCH_H; + me->setRegeneratingHealth(false); + } + + void SetData(uint32 type, uint32 data) OVERRIDE + { + if (type == ACTION_SET_SLOT && data < MAX_SLOTS) + { + SetSlotInfo(data); + + me->SetReactState(REACT_PASSIVE); + + float x, y, z, o; + Slot->TargetPosition.GetPosition(x, y, z, o); + + me->SetTransportHomePosition(Slot->TargetPosition); + float hx = x, hy = y, hz = z, ho = o; + me->GetTransport()->CalculatePassengerPosition(hx, hy, hz, &ho); + me->SetHomePosition(hx, hy, hz, ho); + + me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, Slot->TargetPosition, false); + + Movement::MoveSplineInit init(me); + init.DisableTransportPathTransformations(); + init.MoveTo(x, y, z, false); + init.Launch(); + } + } + + void EnterEvadeMode() OVERRIDE + { + if (!me->IsAlive() || !me->IsInCombat()) + return; + + me->DeleteThreatList(); + me->CombatStop(true); + me->GetMotionMaster()->MoveTargetedHome(); + } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + if (Slot) + if (Creature* captain = me->FindNearestCreature(Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? NPC_IGB_MURADIN_BRONZEBEARD : NPC_IGB_HIGH_OVERLORD_SAURFANG, 200.0f)) + captain->AI()->SetData(ACTION_CLEAR_SLOT, Index); + } + + void MovementInform(uint32 type, uint32 pointId) OVERRIDE + { + if (type != POINT_MOTION_TYPE) + return; + + if (pointId == EVENT_CHARGE_PREPATH && Slot) + { + me->SetFacingTo(Slot->TargetPosition.GetOrientation()); + me->m_Events.AddEvent(new BattleExperienceEvent(me), me->m_Events.CalculateTime(BattleExperienceEvent::ExperiencedTimes[0])); + DoCast(me, SPELL_BATTLE_EXPERIENCE, true); + me->SetReactState(REACT_AGGRESSIVE); + } + } + + bool CanAIAttack(Unit const* target) const OVERRIDE + { + if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS) + return false; + return target->HasAura(Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_ON_ORGRIMS_HAMMER_DECK : SPELL_ON_SKYBREAKER_DECK); + } + +protected: + void SetSlotInfo(uint32 index) + { + Index = index; + Slot = &((Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SkybreakerSlotInfo : OrgrimsHammerSlotInfo)[Index]); + } + + bool SelectVictim() + { + if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS) + { + EnterEvadeMode(); + return false; + } + + if (!me->HasReactState(REACT_PASSIVE)) + { + if (Unit* victim = me->SelectVictim()) + AttackStart(victim); + return me->GetVictim(); + } + else if (me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return false; + } + + return true; + } + + void TriggerBurningPitch() + { + if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == IN_PROGRESS && + !me->HasUnitState(UNIT_STATE_CASTING) && !me->HasReactState(REACT_PASSIVE) && + !me->HasSpellCooldown(BurningPitchId)) + { + DoCastAOE(BurningPitchId, true); + me->_AddCreatureSpellCooldown(BurningPitchId, time(NULL) + urand(3000, 4000) / IN_MILLISECONDS); + } + } + + InstanceScript* Instance; + SlotInfo const* Slot; + uint32 Index; + uint32 BurningPitchId; +}; + +class npc_gunship : public CreatureScript +{ + public: + npc_gunship() : CreatureScript("npc_gunship") { } + + struct npc_gunshipAI : public NullCreatureAI + { + npc_gunshipAI(Creature* creature) : NullCreatureAI(creature), + _teamInInstance(creature->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE)), + _summonedFirstMage(false), _died(false) + { + me->setRegeneratingHealth(false); + } + + void DamageTaken(Unit* /*source*/, uint32& damage) OVERRIDE + { + if (damage >= me->GetHealth()) + { + JustDied(NULL); + damage = me->GetHealth() - 1; + return; + } + + if (_summonedFirstMage) + return; + + if (me->GetTransport()->GetEntry() != uint32(_teamInInstance == HORDE ? GO_THE_SKYBREAKER_H : GO_ORGRIMS_HAMMER_A)) + return; + + if (!me->HealthBelowPctDamaged(90, damage)) + return; + + _summonedFirstMage = true; + if (Creature* captain = me->FindNearestCreature(_teamInInstance == HORDE ? NPC_IGB_MURADIN_BRONZEBEARD : NPC_IGB_HIGH_OVERLORD_SAURFANG, 100.0f)) + captain->AI()->DoAction(ACTION_SPAWN_MAGE); + } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + if (_died) + return; + + _died = true; + + bool isVictory = me->GetTransport()->GetEntry() == GO_THE_SKYBREAKER_H || me->GetTransport()->GetEntry() == GO_ORGRIMS_HAMMER_A; + InstanceScript* instance = me->GetInstanceScript(); + instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, isVictory ? DONE : FAIL); + if (Creature* creature = me->FindNearestCreature(me->GetEntry() == NPC_ORGRIMS_HAMMER ? NPC_THE_SKYBREAKER : NPC_ORGRIMS_HAMMER, 200.0f)) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, creature); + creature->RemoveAurasDueToSpell(SPELL_CHECK_FOR_PLAYERS); + } + + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + me->RemoveAurasDueToSpell(SPELL_CHECK_FOR_PLAYERS); + + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, 0); + std::list<Creature*> creatures; + GetCreatureListWithEntryInGrid(creatures, me, NPC_MARTYR_STALKER_IGB_SAURFANG, SIZE_OF_GRIDS); + for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + Creature* stalker = *itr; + stalker->RemoveAllAuras(); + stalker->DeleteThreatList(); + stalker->CombatStop(true); + } + + uint32 explosionSpell = isVictory ? SPELL_EXPLOSION_VICTORY : SPELL_EXPLOSION_WIPE; + creatures.clear(); + GetCreatureListWithEntryInGrid(creatures, me, NPC_GUNSHIP_HULL, 200.0f); + for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + Creature* hull = *itr; + if (hull->GetTransport() != me->GetTransport()) + continue; + + hull->CastSpell(hull, explosionSpell, TRIGGERED_FULL_MASK); + } + + creatures.clear(); + GetCreatureListWithEntryInGrid(creatures, me, _teamInInstance == HORDE ? NPC_HORDE_GUNSHIP_CANNON : NPC_ALLIANCE_GUNSHIP_CANNON, 200.0f); + for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + Creature* cannon = *itr; + if (isVictory) + { + cannon->CastSpell(cannon, SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO, TRIGGERED_FULL_MASK); + + WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, cannon->GetPackGUID().size() + 4); + data.append(cannon->GetPackGUID()); + data << uint32(0); + cannon->SendMessageToSet(&data, true); + + cannon->RemoveVehicleKit(); + } + else + cannon->CastSpell(cannon, SPELL_EJECT_ALL_PASSENGERS_WIPE, TRIGGERED_FULL_MASK); + } + + uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD; + uint8 textId = isVictory ? SAY_MURADIN_VICTORY : SAY_MURADIN_WIPE; + if (_teamInInstance == HORDE) + { + creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG; + textId = isVictory ? SAY_SAURFANG_VICTORY : SAY_SAURFANG_WIPE; + } + + if (Creature* creature = me->FindNearestCreature(creatureEntry, 100.0f)) + creature->AI()->Talk(textId); + + if (isVictory) + { + if (GameObject* go = HashMapHolder<GameObject>::Find(instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE))) + if (Transport* otherTransport = go->ToTransport()) + otherTransport->EnableMovement(true); + + me->GetTransport()->EnableMovement(true); + + if (Creature* ship = me->FindNearestCreature(_teamInInstance == HORDE ? NPC_ORGRIMS_HAMMER : NPC_THE_SKYBREAKER, 200.0f)) + { + ship->CastSpell(ship, SPELL_TELEPORT_PLAYERS_ON_VICTORY, TRIGGERED_FULL_MASK); + ship->CastSpell(ship, SPELL_ACHIEVEMENT, TRIGGERED_FULL_MASK); + ship->CastSpell(ship, SPELL_AWARD_REPUTATION_BOSS_KILL, TRIGGERED_FULL_MASK); + } + + creatures.clear(); + GetCreatureListWithEntryInGrid(creatures, me, NPC_SKYBREAKER_MARINE, 200.0f); + GetCreatureListWithEntryInGrid(creatures, me, NPC_SKYBREAKER_SERGEANT, 200.0f); + GetCreatureListWithEntryInGrid(creatures, me, NPC_KOR_KRON_REAVER, 200.0f); + GetCreatureListWithEntryInGrid(creatures, me, NPC_KOR_KRON_SERGEANT, 200.0f); + for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + (*itr)->DespawnOrUnsummon(1); + } + else + { + uint32 teleportSpellId = _teamInInstance == HORDE ? SPELL_TELEPORT_PLAYERS_ON_RESET_H : SPELL_TELEPORT_PLAYERS_ON_RESET_A; + me->m_Events.AddEvent(new ResetEncounterEvent(me, teleportSpellId, me->GetInstanceScript()->GetData64(DATA_ENEMY_GUNSHIP)), + me->m_Events.CalculateTime(8000)); + } + } + + void SetGUID(uint64 guid, int32 id/* = 0*/) OVERRIDE + { + if (id != ACTION_SHIP_VISITS) + return; + + std::map<uint64, uint32>::iterator itr = _shipVisits.find(guid); + if (itr == _shipVisits.end()) + _shipVisits[guid] = 1; + else + ++itr->second; + } + + uint32 GetData(uint32 id) const OVERRIDE + { + if (id != ACTION_SHIP_VISITS) + return 0; + + uint32 max = 0; + for (std::map<uint64, uint32>::const_iterator itr = _shipVisits.begin(); itr != _shipVisits.end(); ++itr) + max = std::max(max, itr->second); + + return max; + } + + private: + uint32 _teamInInstance; + std::map<uint64, uint32> _shipVisits; + bool _summonedFirstMage; + bool _died; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + if (!creature->GetTransport()) + return NULL; + + return GetIcecrownCitadelAI<npc_gunshipAI>(creature); + } +}; + +class npc_high_overlord_saurfang_igb : public CreatureScript +{ + public: + npc_high_overlord_saurfang_igb() : CreatureScript("npc_high_overlord_saurfang_igb") { } + + struct npc_high_overlord_saurfang_igbAI : public ScriptedAI + { + npc_high_overlord_saurfang_igbAI(Creature* creature) : ScriptedAI(creature), + _instance(creature->GetInstanceScript()) + { + _controller.ResetSlots(HORDE); + _controller.SetTransport(creature->GetTransport()); + me->setRegeneratingHealth(false); + me->m_CombatDistance = 70.0f; + _firstMageCooldown = time(NULL) + 60; + _axethrowersYellCooldown = time_t(0); + _rocketeersYellCooldown = time_t(0); + } + + void InitializeAI() OVERRIDE + { + ScriptedAI::InitializeAI(); + + _events.Reset(); + _firstMageCooldown = time(NULL) + 60; + _axethrowersYellCooldown = time_t(0); + _rocketeersYellCooldown = time_t(0); + } + + void EnterCombat(Unit* /*target*/) OVERRIDE + { + _events.SetPhase(PHASE_COMBAT); + DoCast(me, _instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_FRIENDLY_BOSS_DAMAGE_MOD : SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER, true); + DoCast(me, SPELL_BATTLE_FURY, true); + _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000)); + } + + void EnterEvadeMode() OVERRIDE + { + if (!me->IsAlive()) + return; + + me->DeleteThreatList(); + me->CombatStop(true); + me->GetMotionMaster()->MoveTargetedHome(); + + Reset(); + } + + void DoAction(int32 action) OVERRIDE + { + if (action == ACTION_ENEMY_GUNSHIP_TALK) + { + if (Creature* muradin = me->FindNearestCreature(NPC_IGB_MURADIN_BRONZEBEARD, 100.0f)) + muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS); + + Talk(SAY_SAURFANG_INTRO_5); + _events.ScheduleEvent(EVENT_INTRO_H_5, 4000); + _events.ScheduleEvent(EVENT_INTRO_H_6, 11000); + _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, 1); + + _instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, IN_PROGRESS); + // Combat starts now + if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f)) + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, skybreaker, 1); + + if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f)) + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, orgrimsHammer, 2); + orgrimsHammer->CastSpell(orgrimsHammer, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK); + } + + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_ENCOUNTER); + } + else if (action == ACTION_SPAWN_MAGE) + { + time_t now = time(NULL); + if (_firstMageCooldown > now) + _events.ScheduleEvent(EVENT_SUMMON_MAGE, (_firstMageCooldown - now) * IN_MILLISECONDS); + else + _events.ScheduleEvent(EVENT_SUMMON_MAGE, 1); + } + else if (action == ACTION_SPAWN_ALL_ADDS) + { + _events.ScheduleEvent(EVENT_ADDS, 12000); + _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 13000); + _events.ScheduleEvent(EVENT_CHECK_MORTAR, 13000); + if (Is25ManRaid()) + _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MORTAR_4); + else + { + _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2); + _controller.SummonCreatures(SLOT_MORTAR_1, SLOT_MORTAR_2); + _controller.SummonCreatures(SLOT_RIFLEMAN_1, SLOT_RIFLEMAN_4); + } + } + else if (action == ACTION_EXIT_SHIP) + { + Position pos; + pos.Relocate(SaurfangExitPath[SaurfangExitPathSize - 1].x, SaurfangExitPath[SaurfangExitPathSize - 1].y, SaurfangExitPath[SaurfangExitPathSize - 1].z); + me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, pos, false); + + Movement::PointsArray path(SaurfangExitPath, SaurfangExitPath + SaurfangExitPathSize); + + Movement::MoveSplineInit init(me); + init.DisableTransportPathTransformations(); + init.MovebyPath(path, 0); + init.Launch(); + + me->DespawnOrUnsummon(18000); + } + } + + void SetData(uint32 type, uint32 data) OVERRIDE + { + if (type == ACTION_CLEAR_SLOT) + { + _controller.ClearSlot(PassengerSlots(data)); + if (data == SLOT_FREEZE_MAGE) + _events.ScheduleEvent(EVENT_SUMMON_MAGE, urand(30000, 33500)); + } + } + + void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) OVERRIDE + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->GetTransport()->EnableMovement(true); + _events.SetPhase(PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_H_1, 5000, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_H_2, 16000, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_SUMMON_SKYBREAKER, 24600, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_H_3, 29600, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_H_4, 39200, 0, PHASE_INTRO); + } + + void DamageTaken(Unit* , uint32& damage) OVERRIDE + { + if (me->HealthBelowPctDamaged(65, damage) && !me->HasAura(SPELL_TASTE_OF_BLOOD)) + DoCast(me, SPELL_TASTE_OF_BLOOD, true); + + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + } + + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO) && _instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_INTRO_H_1: + Talk(SAY_SAURFANG_INTRO_1); + break; + case EVENT_INTRO_H_2: + Talk(SAY_SAURFANG_INTRO_2); + break; + case EVENT_INTRO_SUMMON_SKYBREAKER: + sTransportMgr->CreateTransport(GO_THE_SKYBREAKER_H, 0, me->GetMap()); + break; + case EVENT_INTRO_H_3: + Talk(SAY_SAURFANG_INTRO_3); + break; + case EVENT_INTRO_H_4: + Talk(SAY_SAURFANG_INTRO_4); + break; + case EVENT_INTRO_H_5: + if (Creature* muradin = me->FindNearestCreature(NPC_IGB_MURADIN_BRONZEBEARD, 100.0f)) + muradin->AI()->Talk(SAY_MURADIN_INTRO_H); + break; + case EVENT_INTRO_H_6: + Talk(SAY_SAURFANG_INTRO_6); + break; + case EVENT_KEEP_PLAYER_IN_COMBAT: + if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == IN_PROGRESS) + { + _instance->DoCastSpellOnPlayers(SPELL_LOCK_PLAYERS_AND_TAP_CHEST); + _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, urand(5000, 8000)); + } + break; + case EVENT_SUMMON_MAGE: + Talk(SAY_SAURFANG_MAGES); + _controller.SummonCreatures(SLOT_FREEZE_MAGE, SLOT_FREEZE_MAGE); + break; + case EVENT_ADDS: + Talk(SAY_SAURFANG_ENTER_SKYBREAKER); + _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2); + _controller.SummonCreatures(SLOT_MARINE_1, Is25ManRaid() ? SLOT_MARINE_4 : SLOT_MARINE_2); + _controller.SummonCreatures(SLOT_SERGEANT_1, Is25ManRaid() ? SLOT_SERGEANT_2 : SLOT_SERGEANT_1); + if (Transport* orgrimsHammer = me->GetTransport()) + orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000); + + if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE))) + if (Transport* skybreaker = go->ToTransport()) + skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); + + _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); + _events.ScheduleEvent(EVENT_ADDS, 60000); + break; + case EVENT_ADDS_BOARD_YELL: + if (Creature* muradin = me->FindNearestCreature(NPC_IGB_MURADIN_BRONZEBEARD, 200.0f)) + muradin->AI()->Talk(SAY_MURADIN_BOARD); + break; + case EVENT_CHECK_RIFLEMAN: + if (_controller.SummonCreatures(SLOT_RIFLEMAN_1, Is25ManRaid() ? SLOT_RIFLEMAN_8 : SLOT_RIFLEMAN_4)) + { + if (_axethrowersYellCooldown < time(NULL)) + { + Talk(SAY_SAURFANG_AXETHROWERS); + _axethrowersYellCooldown = time(NULL) + 5; + } + } + _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 1000); + break; + case EVENT_CHECK_MORTAR: + if (_controller.SummonCreatures(SLOT_MORTAR_1, Is25ManRaid() ? SLOT_MORTAR_4 : SLOT_MORTAR_2)) + { + if (_rocketeersYellCooldown < time(NULL)) + { + Talk(SAY_SAURFANG_ROCKETEERS); + _rocketeersYellCooldown = time(NULL) + 5; + } + } + _events.ScheduleEvent(EVENT_CHECK_MORTAR, 1000); + break; + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000)); + break; + default: + break; + } + } + + if (me->IsWithinMeleeRange(me->GetVictim())) + DoMeleeAttackIfReady(); + else if (me->isAttackReady()) + { + DoCastVictim(SPELL_RENDING_THROW); + me->resetAttackTimer(); + } + } + + bool CanAIAttack(Unit const* target) const OVERRIDE + { + if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS) + return false; + return target->HasAura(SPELL_ON_ORGRIMS_HAMMER_DECK) || target->GetEntry() == NPC_SKYBREAKER_MARINE || target->GetEntry() == NPC_SKYBREAKER_SERGEANT; + } + + private: + EventMap _events; + PassengerController _controller; + InstanceScript* _instance; + time_t _firstMageCooldown; + time_t _axethrowersYellCooldown; + time_t _rocketeersYellCooldown; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_high_overlord_saurfang_igbAI>(creature); + } +}; + +class npc_muradin_bronzebeard_igb : public CreatureScript +{ + public: + npc_muradin_bronzebeard_igb() : CreatureScript("npc_muradin_bronzebeard_igb") { } + + struct npc_muradin_bronzebeard_igbAI : public ScriptedAI + { + npc_muradin_bronzebeard_igbAI(Creature* creature) : ScriptedAI(creature), + _instance(creature->GetInstanceScript()) + { + _controller.ResetSlots(ALLIANCE); + _controller.SetTransport(creature->GetTransport()); + me->setRegeneratingHealth(false); + me->m_CombatDistance = 70.0f; + _firstMageCooldown = time(NULL) + 60; + _riflemanYellCooldown = time_t(0); + _mortarYellCooldown = time_t(0); + } + + void InitializeAI() OVERRIDE + { + ScriptedAI::InitializeAI(); + + _events.Reset(); + _firstMageCooldown = time(NULL) + 60; + _riflemanYellCooldown = time_t(0); + _mortarYellCooldown = time_t(0); + } + + void EnterCombat(Unit* /*target*/) OVERRIDE + { + _events.SetPhase(PHASE_COMBAT); + DoCast(me, _instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE ? SPELL_FRIENDLY_BOSS_DAMAGE_MOD : SPELL_MELEE_TARGETING_ON_SKYBREAKER, true); + DoCast(me, SPELL_BATTLE_FURY, true); + _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000)); + } + + void EnterEvadeMode() OVERRIDE + { + if (!me->IsAlive()) + return; + + me->DeleteThreatList(); + me->CombatStop(true); + me->GetMotionMaster()->MoveTargetedHome(); + + Reset(); + } + + void DoAction(int32 action) OVERRIDE + { + if (action == ACTION_ENEMY_GUNSHIP_TALK) + { + if (Creature* muradin = me->FindNearestCreature(NPC_IGB_HIGH_OVERLORD_SAURFANG, 100.0f)) + muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS); + + Talk(SAY_MURADIN_INTRO_6); + _events.ScheduleEvent(EVENT_INTRO_A_6, 5000); + _events.ScheduleEvent(EVENT_INTRO_A_7, 11000); + _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, 1); + + _instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, IN_PROGRESS); + // Combat starts now + if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f)) + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, orgrimsHammer, 1); + + if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f)) + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, skybreaker, 2); + skybreaker->CastSpell(skybreaker, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK); + } + + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_ENCOUNTER); + } + else if (action == ACTION_SPAWN_MAGE) + { + time_t now = time(NULL); + if (_firstMageCooldown > now) + _events.ScheduleEvent(EVENT_SUMMON_MAGE, (_firstMageCooldown - now) * IN_MILLISECONDS); + else + _events.ScheduleEvent(EVENT_SUMMON_MAGE, 1); + } + else if (action == ACTION_SPAWN_ALL_ADDS) + { + _events.ScheduleEvent(EVENT_ADDS, 12000); + _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 13000); + _events.ScheduleEvent(EVENT_CHECK_MORTAR, 13000); + if (Is25ManRaid()) + _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MORTAR_4); + else + { + _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2); + _controller.SummonCreatures(SLOT_MORTAR_1, SLOT_MORTAR_2); + _controller.SummonCreatures(SLOT_RIFLEMAN_1, SLOT_RIFLEMAN_4); + } + } + else if (action == ACTION_EXIT_SHIP) + { + Position pos; + pos.Relocate(MuradinExitPath[MuradinExitPathSize - 1].x, MuradinExitPath[MuradinExitPathSize - 1].y, MuradinExitPath[MuradinExitPathSize - 1].z); + me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, pos, false); + + Movement::PointsArray path(MuradinExitPath, MuradinExitPath + MuradinExitPathSize); + + Movement::MoveSplineInit init(me); + init.DisableTransportPathTransformations(); + init.MovebyPath(path, 0); + init.Launch(); + + me->DespawnOrUnsummon(18000); + } + } + + void SetData(uint32 type, uint32 data) OVERRIDE + { + if (type == ACTION_CLEAR_SLOT) + { + _controller.ClearSlot(PassengerSlots(data)); + if (data == SLOT_FREEZE_MAGE) + _events.ScheduleEvent(EVENT_SUMMON_MAGE, urand(30000, 33500)); + } + } + + void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) OVERRIDE + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->GetTransport()->EnableMovement(true); + _events.SetPhase(PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_A_1, 5000); + _events.ScheduleEvent(EVENT_INTRO_A_2, 10000, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_SUMMON_ORGRIMS_HAMMER, 28000, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_A_3, 33000, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_A_4, 39000, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_A_5, 45000, 0, PHASE_INTRO); + } + + void DamageTaken(Unit* , uint32& damage) OVERRIDE + { + if (me->HealthBelowPctDamaged(65, damage) && me->HasAura(SPELL_TASTE_OF_BLOOD)) + DoCast(me, SPELL_TASTE_OF_BLOOD, true); + + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + } + + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO) && _instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_INTRO_A_1: + Talk(SAY_MURADIN_INTRO_1); + break; + case EVENT_INTRO_A_2: + Talk(SAY_MURADIN_INTRO_2); + break; + case EVENT_INTRO_SUMMON_ORGRIMS_HAMMER: + sTransportMgr->CreateTransport(GO_ORGRIMS_HAMMER_A, 0, me->GetMap()); + break; + case EVENT_INTRO_A_3: + Talk(SAY_MURADIN_INTRO_3); + break; + case EVENT_INTRO_A_4: + Talk(SAY_MURADIN_INTRO_4); + break; + case EVENT_INTRO_A_5: + Talk(SAY_MURADIN_INTRO_5); + break; + case EVENT_INTRO_A_6: + if (Creature* saurfang = me->FindNearestCreature(NPC_IGB_HIGH_OVERLORD_SAURFANG, 100.0f)) + saurfang->AI()->Talk(SAY_SAURFANG_INTRO_A); + break; + case EVENT_INTRO_A_7: + Talk(SAY_MURADIN_INTRO_7); + break; + case EVENT_KEEP_PLAYER_IN_COMBAT: + if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == IN_PROGRESS) + { + _instance->DoCastSpellOnPlayers(SPELL_LOCK_PLAYERS_AND_TAP_CHEST); + _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, urand(5000, 8000)); + } + break; + case EVENT_SUMMON_MAGE: + Talk(SAY_MURADIN_SORCERERS); + _controller.SummonCreatures(SLOT_FREEZE_MAGE, SLOT_FREEZE_MAGE); + break; + case EVENT_ADDS: + Talk(SAY_MURADIN_ENTER_ORGRIMMS_HAMMER); + _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2); + _controller.SummonCreatures(SLOT_MARINE_1, Is25ManRaid() ? SLOT_MARINE_4 : SLOT_MARINE_2); + _controller.SummonCreatures(SLOT_SERGEANT_1, Is25ManRaid() ? SLOT_SERGEANT_2 : SLOT_SERGEANT_1); + if (Transport* skybreaker = me->GetTransport()) + skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000); + + if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE))) + if (Transport* orgrimsHammer = go->ToTransport()) + orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); + + _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); + _events.ScheduleEvent(EVENT_ADDS, 60000); + break; + case EVENT_ADDS_BOARD_YELL: + if (Creature* saurfang = me->FindNearestCreature(NPC_IGB_HIGH_OVERLORD_SAURFANG, 200.0f)) + saurfang->AI()->Talk(SAY_SAURFANG_BOARD); + break; + case EVENT_CHECK_RIFLEMAN: + if (_controller.SummonCreatures(SLOT_RIFLEMAN_1, Is25ManRaid() ? SLOT_RIFLEMAN_8 : SLOT_RIFLEMAN_4)) + { + if (_riflemanYellCooldown < time(NULL)) + { + Talk(SAY_MURADIN_RIFLEMAN); + _riflemanYellCooldown = time(NULL) + 5; + } + } + _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 1000); + break; + case EVENT_CHECK_MORTAR: + if (_controller.SummonCreatures(SLOT_MORTAR_1, Is25ManRaid() ? SLOT_MORTAR_4 : SLOT_MORTAR_2)) + { + if (_mortarYellCooldown < time(NULL)) + { + Talk(SAY_MURADIN_MORTAR); + _mortarYellCooldown = time(NULL) + 5; + } + } + _events.ScheduleEvent(EVENT_CHECK_MORTAR, 1000); + break; + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000)); + break; + default: + break; + } + } + + if (me->IsWithinMeleeRange(me->GetVictim())) + DoMeleeAttackIfReady(); + else if (me->isAttackReady()) + { + DoCastVictim(SPELL_RENDING_THROW); + me->resetAttackTimer(); + } + } + + bool CanAIAttack(Unit const* target) const OVERRIDE + { + if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS) + return false; + return target->HasAura(SPELL_ON_SKYBREAKER_DECK) || target->GetEntry() == NPC_KOR_KRON_REAVER || target->GetEntry() == NPC_KOR_KRON_SERGEANT; + } + + private: + EventMap _events; + PassengerController _controller; + InstanceScript* _instance; + time_t _firstMageCooldown; + time_t _riflemanYellCooldown; + time_t _mortarYellCooldown; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_muradin_bronzebeard_igbAI>(creature); + } +}; + +class npc_zafod_boombox : public CreatureScript +{ + public: + npc_zafod_boombox() : CreatureScript("npc_zafod_boombox") { } + + struct npc_zafod_boomboxAI : public gunship_npc_AI + { + npc_zafod_boomboxAI(Creature* creature) : gunship_npc_AI(creature) + { + } + + void Reset() OVERRIDE + { + me->SetReactState(REACT_PASSIVE); + } + + void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) OVERRIDE + { + player->AddItem(ITEM_GOBLIN_ROCKET_PACK, 1); + player->PlayerTalkClass->SendCloseGossip(); + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE + { + UpdateVictim(); + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_zafod_boomboxAI>(creature); + } +}; + +struct npc_gunship_boarding_addAI : public gunship_npc_AI +{ + npc_gunship_boarding_addAI(Creature* creature) : gunship_npc_AI(creature) + { + me->m_CombatDistance = 80.0f; + _usedDesperateResolve = false; + } + + void SetData(uint32 type, uint32 data) OVERRIDE + { + // detach from captain + if (type == ACTION_SET_SLOT) + { + SetSlotInfo(data); + + me->SetReactState(REACT_PASSIVE); + + me->m_Events.AddEvent(new DelayedMovementEvent(me, Slot->TargetPosition), me->m_Events.CalculateTime(3000 * (Index - SLOT_MARINE_1))); + + if (Creature* captain = me->FindNearestCreature(Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? NPC_IGB_MURADIN_BRONZEBEARD : NPC_IGB_HIGH_OVERLORD_SAURFANG, 200.0f)) + captain->AI()->SetData(ACTION_CLEAR_SLOT, Index); + } + } + + void MovementInform(uint32 type, uint32 pointId) OVERRIDE + { + if (type != POINT_MOTION_TYPE) + return; + + if (pointId == EVENT_CHARGE_PREPATH && Slot) + { + Position const& otherTransportPos = Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? OrgrimsHammerTeleportExit : SkybreakerTeleportExit; + float x, y, z, o; + otherTransportPos.GetPosition(x, y, z, o); + + Transport* myTransport = me->GetTransport(); + if (!myTransport) + return; + + if (GameObject* go = HashMapHolder<GameObject>::Find(Instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE))) + if (Transport* destTransport = go->ToTransport()) + destTransport->CalculatePassengerPosition(x, y, z, &o); + + float angle = frand(0, M_PI * 2.0f); + x += 2.0f * std::cos(angle); + y += 2.0f * std::sin(angle); + + me->SetHomePosition(x, y, z, o); + myTransport->CalculatePassengerOffset(x, y, z, &o); + me->SetTransportHomePosition(x, y, z, o); + + me->m_Events.AddEvent(new BattleExperienceEvent(me), me->m_Events.CalculateTime(BattleExperienceEvent::ExperiencedTimes[0])); + DoCast(me, SPELL_BATTLE_EXPERIENCE, true); + DoCast(me, SPELL_TELEPORT_TO_ENEMY_SHIP, true); + DoCast(me, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER : SPELL_MELEE_TARGETING_ON_SKYBREAKER, true); + me->_AddCreatureSpellCooldown(BurningPitchId, time(NULL) + 3); + + std::list<Player*> players; + Trinity::UnitAuraCheck check(true, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_ON_ORGRIMS_HAMMER_DECK : SPELL_ON_SKYBREAKER_DECK); + Trinity::PlayerListSearcher<Trinity::UnitAuraCheck> searcher(me, players, check); + me->VisitNearbyWorldObject(200.0f, searcher); + + players.remove_if([this](Player* player) + { + return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true); + }); + + if (!players.empty()) + { + players.sort(Trinity::ObjectDistanceOrderPred(me)); + for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr) + me->AddThreat(*itr, 1.0f); + + AttackStart(players.front()); + } + + me->SetReactState(REACT_AGGRESSIVE); + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) OVERRIDE + { + if (_usedDesperateResolve) + return; + + if (!me->HealthBelowPctDamaged(25, damage)) + return; + + _usedDesperateResolve = true; + DoCast(me, SPELL_DESPERATE_RESOLVE, true); + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE + { + if (!SelectVictim()) + { + TriggerBurningPitch(); + return; + } + + if (!HasAttackablePlayerNearby()) + TriggerBurningPitch(); + + DoMeleeAttackIfReady(); + } + + bool CanAIAttack(Unit const* target) const OVERRIDE + { + uint32 spellId = SPELL_ON_SKYBREAKER_DECK; + uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD; + if (Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE) + { + spellId = SPELL_ON_ORGRIMS_HAMMER_DECK; + creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG; + } + + return target->HasAura(spellId) || target->GetEntry() == creatureEntry; + } + + bool HasAttackablePlayerNearby() + { + std::list<Player*> players; + Trinity::UnitAuraCheck check(true, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_ON_ORGRIMS_HAMMER_DECK : SPELL_ON_SKYBREAKER_DECK); + Trinity::PlayerListSearcher<Trinity::UnitAuraCheck> searcher(me, players, check); + me->VisitNearbyWorldObject(200.0f, searcher); + + players.remove_if([this](Player* player) + { + return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true); + }); + + return !players.empty(); + } + +private: + bool _usedDesperateResolve; +}; + +class npc_gunship_boarding_leader : public CreatureScript +{ + public: + npc_gunship_boarding_leader() : CreatureScript("npc_gunship_boarding_leader") { } + + struct npc_gunship_boarding_leaderAI : public npc_gunship_boarding_addAI + { + npc_gunship_boarding_leaderAI(Creature* creature) : npc_gunship_boarding_addAI(creature) + { + } + + void EnterCombat(Unit* target) OVERRIDE + { + npc_gunship_boarding_addAI::EnterCombat(target); + _events.ScheduleEvent(EVENT_BLADESTORM, urand(13000, 18000)); + _events.ScheduleEvent(EVENT_WOUNDING_STRIKE, urand(8000, 10000)); + } + + void UpdateAI(uint32 diff) OVERRIDE + { + if (!SelectVictim()) + { + TriggerBurningPitch(); + return; + } + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_BLADESTORM)) + return; + + if (!HasAttackablePlayerNearby()) + TriggerBurningPitch(); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BLADESTORM: + DoCastAOE(SPELL_BLADESTORM); + _events.ScheduleEvent(EVENT_BLADESTORM, urand(25000, 30000)); + break; + case EVENT_WOUNDING_STRIKE: + DoCastVictim(SPELL_WOUNDING_STRIKE); + _events.ScheduleEvent(EVENT_WOUNDING_STRIKE, urand(9000, 13000)); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_gunship_boarding_leaderAI>(creature); + } +}; + +class npc_gunship_boarding_add : public CreatureScript +{ + public: + npc_gunship_boarding_add() : CreatureScript("npc_gunship_boarding_add") { } + + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_gunship_boarding_addAI>(creature); + } +}; + +class npc_gunship_gunner : public CreatureScript +{ + public: + npc_gunship_gunner() : CreatureScript("npc_gunship_gunner") { } + + struct npc_gunship_gunnerAI : public gunship_npc_AI + { + npc_gunship_gunnerAI(Creature* creature) : gunship_npc_AI(creature) + { + creature->m_CombatDistance = 200.0f; + } + + void AttackStart(Unit* target) OVERRIDE + { + me->Attack(target, false); + } + + void MovementInform(uint32 type, uint32 pointId) OVERRIDE + { + gunship_npc_AI::MovementInform(type, pointId); + if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH) + me->SetControlled(true, UNIT_STATE_ROOT); + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE + { + if (!SelectVictim()) + { + TriggerBurningPitch(); + return; + } + + DoSpellAttackIfReady(me->GetEntry() == NPC_SKYBREAKER_RIFLEMAN ? SPELL_SHOOT : SPELL_HURL_AXE); + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_gunship_gunnerAI>(creature); + } +}; + +class npc_gunship_rocketeer : public CreatureScript +{ + public: + npc_gunship_rocketeer() : CreatureScript("npc_gunship_rocketeer") { } + + struct npc_gunship_rocketeerAI : public gunship_npc_AI + { + npc_gunship_rocketeerAI(Creature* creature) : gunship_npc_AI(creature) + { + creature->m_CombatDistance = 200.0f; + } + + void MovementInform(uint32 type, uint32 pointId) OVERRIDE + { + gunship_npc_AI::MovementInform(type, pointId); + if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH) + me->SetControlled(true, UNIT_STATE_ROOT); + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE + { + if (!SelectVictim()) + return; + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + uint32 spellId = me->GetEntry() == NPC_SKYBREAKER_MORTAR_SOLDIER ? SPELL_ROCKET_ARTILLERY_A : SPELL_ROCKET_ARTILLERY_H; + if (me->HasSpellCooldown(spellId)) + return; + + DoCastAOE(spellId, true); + me->_AddCreatureSpellCooldown(spellId, time(NULL) + 9); + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_gunship_rocketeerAI>(creature); + } +}; + +class npc_gunship_mage : public CreatureScript +{ + public: + npc_gunship_mage() : CreatureScript("npc_gunship_mage") { } + + struct npc_gunship_mageAI : public gunship_npc_AI + { + npc_gunship_mageAI(Creature* creature) : gunship_npc_AI(creature) + { + me->SetReactState(REACT_PASSIVE); + } + + void EnterEvadeMode() OVERRIDE + { + ScriptedAI::EnterEvadeMode(); + } + + void MovementInform(uint32 type, uint32 pointId) OVERRIDE + { + if (type != POINT_MOTION_TYPE) + return; + + if (pointId == EVENT_CHARGE_PREPATH && Slot) + { + SlotInfo const* slots = Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SkybreakerSlotInfo : OrgrimsHammerSlotInfo; + me->SetFacingTo(slots[Index].TargetPosition.GetOrientation()); + switch (Index) + { + case SLOT_FREEZE_MAGE: + DoCastAOE(SPELL_BELOW_ZERO); + break; + case SLOT_MAGE_1: + case SLOT_MAGE_2: + DoCastAOE(SPELL_SHADOW_CHANNELING); + break; + default: + break; + } + + me->SetControlled(true, UNIT_STATE_ROOT); + } + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE + { + UpdateVictim(); + } + + bool CanAIAttack(Unit const* /*target*/) const OVERRIDE + { + return true; + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetIcecrownCitadelAI<npc_gunship_mageAI>(creature); + } +}; + +/** @HACK This AI only resets MOVEMENTFLAG_ROOT on the vehicle. + Currently the core always removes MOVEMENTFLAG_ROOT sent from client packets to prevent cheaters from freezing clients of other players + but it actually is a valid flag - needs more research to fix both freezes and keep the flag as is (see WorldSession::ReadMovementInfo) + +Example packet: +ClientToServer: CMSG_FORCE_MOVE_ROOT_ACK (0x00E9) Length: 67 ConnectionIndex: 0 Time: 03/04/2010 03:57:55.000 Number: 471326 +Guid: +Movement Counter: 80 +Movement Flags: OnTransport, Root (2560) +Extra Movement Flags: None (0) +Time: 52291611 +Position: X: -396.0302 Y: 2482.906 Z: 249.86 +Orientation: 1.468665 +Transport GUID: Full: 0x1FC0000000000460 Type: MOTransport Low: 1120 +Transport Position: X: -6.152398 Y: -23.49037 Z: 21.64464 O: 4.827727 +Transport Time: 9926 +Transport Seat: 255 +Fall Time: 824 +*/ +class npc_gunship_cannon : public CreatureScript +{ + public: + npc_gunship_cannon() : CreatureScript("npc_gunship_cannon") { } + + struct npc_gunship_cannonAI : public PassiveAI + { + npc_gunship_cannonAI(Creature* creature) : PassiveAI(creature) + { + } + + void OnCharmed(bool /*apply*/) OVERRIDE { } + + void PassengerBoarded(Unit* /*passenger*/, int8 /*seat*/, bool apply) OVERRIDE + { + if (!apply) + { + me->SetControlled(false, UNIT_STATE_ROOT); + me->SetControlled(true, UNIT_STATE_ROOT); + } + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_gunship_cannonAI(creature); + } +}; + +class spell_igb_rocket_pack : public SpellScriptLoader +{ + public: + spell_igb_rocket_pack() : SpellScriptLoader("spell_igb_rocket_pack") { } + + class spell_igb_rocket_pack_AuraScript : public AuraScript + { + PrepareAuraScript(spell_igb_rocket_pack_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROCKET_PACK_DAMAGE) || + !sSpellMgr->GetSpellInfo(SPELL_ROCKET_BURST)) + return false; + + return true; + } + + void HandlePeriodic(AuraEffect const* /*aurEff*/) + { + if (GetTarget()->movespline->Finalized()) + Remove(AURA_REMOVE_BY_EXPIRE); + } + + void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + SpellInfo const* damageInfo = sSpellMgr->EnsureSpellInfo(SPELL_ROCKET_PACK_DAMAGE); + GetTarget()->CastCustomSpell(SPELL_ROCKET_PACK_DAMAGE, SPELLVALUE_BASE_POINT0, 2 * (damageInfo->Effects[EFFECT_0].CalcValue() + aurEff->GetTickNumber() * aurEff->GetAmplitude()), NULL, TRIGGERED_FULL_MASK); + GetTarget()->CastSpell(NULL, SPELL_ROCKET_BURST, TRIGGERED_FULL_MASK); + } + + void Register() OVERRIDE + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_igb_rocket_pack_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectRemove += AuraEffectRemoveFn(spell_igb_rocket_pack_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_igb_rocket_pack_AuraScript(); + } +}; + +class spell_igb_rocket_pack_useable : public SpellScriptLoader +{ + public: + spell_igb_rocket_pack_useable() : SpellScriptLoader("spell_igb_rocket_pack_useable") { } + + class spell_igb_rocket_pack_useable_AuraScript : public AuraScript + { + PrepareAuraScript(spell_igb_rocket_pack_useable_AuraScript); + + bool Load() + { + return GetOwner()->GetInstanceScript(); + } + + bool CheckAreaTarget(Unit* target) + { + return target->GetTypeId() == TYPEID_PLAYER && GetOwner()->GetInstanceScript()->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* owner = GetOwner()->ToCreature()) + if (Player* target = GetTarget()->ToPlayer()) + if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1)) + sCreatureTextMgr->SendChat(owner, SAY_ZAFOD_ROCKET_PACK_ACTIVE, target, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, target); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* owner = GetOwner()->ToCreature()) + if (Player* target = GetTarget()->ToPlayer()) + if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1)) + sCreatureTextMgr->SendChat(owner, SAY_ZAFOD_ROCKET_PACK_DISABLED, target, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, target); + } + + void Register() OVERRIDE + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_igb_rocket_pack_useable_AuraScript::CheckAreaTarget); + AfterEffectApply += AuraEffectApplyFn(spell_igb_rocket_pack_useable_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_igb_rocket_pack_useable_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_igb_rocket_pack_useable_AuraScript(); + } +}; + +class spell_igb_on_gunship_deck : public SpellScriptLoader +{ + public: + spell_igb_on_gunship_deck() : SpellScriptLoader("spell_igb_on_gunship_deck") { } + + class spell_igb_on_gunship_deck_AuraScript : public AuraScript + { + PrepareAuraScript(spell_igb_on_gunship_deck_AuraScript); + + bool Load() OVERRIDE + { + if (InstanceScript* instance = GetOwner()->GetInstanceScript()) + _teamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE); + else + _teamInInstance = 0; + return true; + } + + bool CheckAreaTarget(Unit* unit) + { + return unit->GetTypeId() == TYPEID_PLAYER; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetSpellInfo()->Id == uint32(_teamInInstance == HORDE ? SPELL_ON_SKYBREAKER_DECK : SPELL_ON_ORGRIMS_HAMMER_DECK)) + if (Creature* gunship = GetOwner()->FindNearestCreature(_teamInInstance == HORDE ? NPC_ORGRIMS_HAMMER : NPC_THE_SKYBREAKER, 200.0f)) + gunship->AI()->SetGUID(GetTarget()->GetGUID(), ACTION_SHIP_VISITS); + } + + void Register() OVERRIDE + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_igb_on_gunship_deck_AuraScript::CheckAreaTarget); + AfterEffectApply += AuraEffectApplyFn(spell_igb_on_gunship_deck_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + + uint32 _teamInInstance; + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_igb_on_gunship_deck_AuraScript(); + } +}; + +class spell_igb_periodic_trigger_with_power_cost : public SpellScriptLoader +{ + public: + spell_igb_periodic_trigger_with_power_cost() : SpellScriptLoader("spell_igb_periodic_trigger_with_power_cost") { } + + class spell_igb_periodic_trigger_with_power_cost_AuraScript : public AuraScript + { + PrepareAuraScript(spell_igb_periodic_trigger_with_power_cost_AuraScript); + + void HandlePeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); + } + + void Register() OVERRIDE + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_igb_periodic_trigger_with_power_cost_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_igb_periodic_trigger_with_power_cost_AuraScript(); + } +}; + +class spell_igb_cannon_blast : public SpellScriptLoader +{ + public: + spell_igb_cannon_blast() : SpellScriptLoader("spell_igb_cannon_blast") { } + + class spell_igb_cannon_blast_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_cannon_blast_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void CheckEnergy() + { + if (GetCaster()->GetPower(POWER_ENERGY) >= 100) + { + GetCaster()->CastSpell(GetCaster(), SPELL_OVERHEAT, TRIGGERED_FULL_MASK); + if (Vehicle* vehicle = GetCaster()->GetVehicleKit()) + if (Unit* passenger = vehicle->GetPassenger(0)) + sCreatureTextMgr->SendChat(GetCaster()->ToCreature(), SAY_OVERHEAT, passenger); + } + } + + void Register() OVERRIDE + { + AfterHit += SpellHitFn(spell_igb_cannon_blast_SpellScript::CheckEnergy); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_cannon_blast_SpellScript(); + } +}; + +class spell_igb_incinerating_blast : public SpellScriptLoader +{ + public: + spell_igb_incinerating_blast() : SpellScriptLoader("spell_igb_incinerating_blast") { } + + class spell_igb_incinerating_blast_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_incinerating_blast_SpellScript); + + void StoreEnergy() + { + _energyLeft = GetCaster()->GetPower(POWER_ENERGY) - 10; + } + + void RemoveEnergy() + { + GetCaster()->SetPower(POWER_ENERGY, 0); + } + + void CalculateDamage(SpellEffIndex /*effIndex*/) + { + SetEffectValue(GetEffectValue() + _energyLeft * _energyLeft * 8); + } + + void Register() OVERRIDE + { + OnCast += SpellCastFn(spell_igb_incinerating_blast_SpellScript::StoreEnergy); + AfterCast += SpellCastFn(spell_igb_incinerating_blast_SpellScript::RemoveEnergy); + OnEffectLaunchTarget += SpellEffectFn(spell_igb_incinerating_blast_SpellScript::CalculateDamage, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE); + } + + uint32 _energyLeft; + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_incinerating_blast_SpellScript(); + } +}; + +class spell_igb_overheat : public SpellScriptLoader +{ + public: + spell_igb_overheat() : SpellScriptLoader("spell_igb_overheat") { } + + class spell_igb_overheat_AuraScript : public AuraScript + { + PrepareAuraScript(spell_igb_overheat_AuraScript); + + bool Load() OVERRIDE + { + if (GetAura()->GetType() != UNIT_AURA_TYPE) + return false; + return GetUnitOwner()->IsVehicle(); + } + + void SendClientControl(uint8 value) + { + if (Vehicle* vehicle = GetUnitOwner()->GetVehicleKit()) + { + if (Unit* passenger = vehicle->GetPassenger(0)) + { + if (Player* player = passenger->ToPlayer()) + { + WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, GetUnitOwner()->GetPackGUID().size() + 1); + data.append(GetUnitOwner()->GetPackGUID()); + data << uint8(value); + player->GetSession()->SendPacket(&data); + } + } + } + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + SendClientControl(0); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + SendClientControl(1); + } + + void Register() OVERRIDE + { + AfterEffectApply += AuraEffectApplyFn(spell_igb_overheat_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_igb_overheat_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_igb_overheat_AuraScript(); + } +}; + +class spell_igb_below_zero : public SpellScriptLoader +{ + public: + spell_igb_below_zero() : SpellScriptLoader("spell_igb_below_zero") { } + + class spell_igb_below_zero_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_below_zero_SpellScript); + + void RemovePassengers() + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO, TRIGGERED_FULL_MASK); + } + + void Register() OVERRIDE + { + BeforeHit += SpellHitFn(spell_igb_below_zero_SpellScript::RemovePassengers); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_below_zero_SpellScript(); + } +}; + +class spell_igb_teleport_to_enemy_ship : public SpellScriptLoader +{ + public: + spell_igb_teleport_to_enemy_ship() : SpellScriptLoader("spell_igb_teleport_to_enemy_ship") { } + + class spell_igb_teleport_to_enemy_ship_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_teleport_to_enemy_ship_SpellScript); + + void RelocateTransportOffset(SpellEffIndex /*effIndex*/) + { + WorldLocation const* dest = GetHitDest(); + Unit* target = GetHitUnit(); + if (!dest || !target || !target->GetTransport()) + return; + + float x, y, z, o; + dest->GetPosition(x, y, z, o); + target->GetTransport()->CalculatePassengerOffset(x, y, z, &o); + target->m_movementInfo.transport.pos.Relocate(x, y, z, o); + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_igb_teleport_to_enemy_ship_SpellScript::RelocateTransportOffset, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_teleport_to_enemy_ship_SpellScript(); + } +}; + +class spell_igb_burning_pitch_selector : public SpellScriptLoader +{ + public: + spell_igb_burning_pitch_selector() : SpellScriptLoader("spell_igb_burning_pitch_selector") { } + + class spell_igb_burning_pitch_selector_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_burning_pitch_selector_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + uint32 team = HORDE; + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + team = instance->GetData(DATA_TEAM_IN_INSTANCE); + + targets.remove_if([team](WorldObject* target) -> bool + { + if (Transport* transport = target->GetTransport()) + return transport->GetEntry() != uint32(team == HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A); + return true; + }); + + if (!targets.empty()) + { + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + } + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), TRIGGERED_NONE); + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_burning_pitch_selector_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_igb_burning_pitch_selector_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_burning_pitch_selector_SpellScript(); + } +}; + +class spell_igb_burning_pitch : public SpellScriptLoader +{ + public: + spell_igb_burning_pitch() : SpellScriptLoader("spell_igb_burning_pitch") { } + + class spell_igb_burning_pitch_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_burning_pitch_SpellScript); + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->CastCustomSpell(uint32(GetEffectValue()), SPELLVALUE_BASE_POINT0, 8000, NULL, TRIGGERED_FULL_MASK); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_BURNING_PITCH, TRIGGERED_FULL_MASK); + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_igb_burning_pitch_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_burning_pitch_SpellScript(); + } +}; + +class spell_igb_rocket_artillery : public SpellScriptLoader +{ + public: + spell_igb_rocket_artillery() : SpellScriptLoader("spell_igb_rocket_artillery") { } + + class spell_igb_rocket_artillery_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_rocket_artillery_SpellScript); + + void SelectRandomTarget(std::list<WorldObject*>& targets) + { + if (!targets.empty()) + { + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), TRIGGERED_NONE); + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_rocket_artillery_SpellScript::SelectRandomTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_igb_rocket_artillery_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_rocket_artillery_SpellScript(); + } +}; + +class spell_igb_rocket_artillery_explosion : public SpellScriptLoader +{ + public: + spell_igb_rocket_artillery_explosion() : SpellScriptLoader("spell_igb_rocket_artillery_explosion") { } + + class spell_igb_rocket_artillery_explosion_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_rocket_artillery_explosion_SpellScript); + + void DamageGunship(SpellEffIndex /*effIndex*/) + { + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + GetCaster()->CastCustomSpell(instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_BURNING_PITCH_DAMAGE_A : SPELL_BURNING_PITCH_DAMAGE_H, SPELLVALUE_BASE_POINT0, 5000, NULL, TRIGGERED_FULL_MASK); + } + + void Register() OVERRIDE + { + OnEffectHit += SpellEffectFn(spell_igb_rocket_artillery_explosion_SpellScript::DamageGunship, EFFECT_0, SPELL_EFFECT_TRIGGER_MISSILE); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_rocket_artillery_explosion_SpellScript(); + } +}; + +class spell_igb_gunship_fall_teleport : public SpellScriptLoader +{ + public: + spell_igb_gunship_fall_teleport() : SpellScriptLoader("spell_igb_gunship_fall_teleport") { } + + class spell_igb_gunship_fall_teleport_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_gunship_fall_teleport_SpellScript); + + bool Load() + { + return GetCaster()->GetInstanceScript(); + } + + void SelectTransport(WorldObject*& target) + { + if (InstanceScript* instance = target->GetInstanceScript()) + target = HashMapHolder<GameObject>::Find(instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE)); + } + + void RelocateDest(SpellEffIndex /*effIndex*/) + { + if (GetCaster()->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE) == HORDE) + GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 36.0f, 0.0f }); + else + GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 21.0f, 0.0f }); + } + + void Register() OVERRIDE + { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_igb_gunship_fall_teleport_SpellScript::SelectTransport, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + OnEffectLaunch += SpellEffectFn(spell_igb_gunship_fall_teleport_SpellScript::RelocateDest, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_gunship_fall_teleport_SpellScript(); + } +}; + +class spell_igb_check_for_players : public SpellScriptLoader +{ + public: + spell_igb_check_for_players() : SpellScriptLoader("spell_igb_check_for_players") { } + + class spell_igb_check_for_players_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_check_for_players_SpellScript); + + bool Load() OVERRIDE + { + _playerCount = 0; + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void CountTargets(std::list<WorldObject*>& targets) + { + _playerCount = targets.size(); + } + + void TriggerWipe() + { + if (!_playerCount) + GetCaster()->ToCreature()->AI()->JustDied(NULL); + } + + void TeleportPlayer(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit()->GetPositionZ() < GetCaster()->GetPositionZ() - 10.0f) + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_GUNSHIP_FALL_TELEPORT, TRIGGERED_FULL_MASK); + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_check_for_players_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + AfterCast += SpellCastFn(spell_igb_check_for_players_SpellScript::TriggerWipe); + OnEffectHitTarget += SpellEffectFn(spell_igb_check_for_players_SpellScript::TeleportPlayer, EFFECT_0, SPELL_EFFECT_DUMMY); + } + + uint32 _playerCount; + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_check_for_players_SpellScript(); + } +}; + +class spell_igb_teleport_players_on_victory : public SpellScriptLoader +{ + public: + spell_igb_teleport_players_on_victory() : SpellScriptLoader("spell_igb_teleport_players_on_victory") { } + + class spell_igb_teleport_players_on_victory_SpellScript : public SpellScript + { + PrepareSpellScript(spell_igb_teleport_players_on_victory_SpellScript); + + bool Load() OVERRIDE + { + return GetCaster()->GetInstanceScript(); + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + InstanceScript* instance = GetCaster()->GetInstanceScript(); + targets.remove_if([instance](WorldObject* target) -> bool + { + return target->GetTransGUID() != instance->GetData64(DATA_ENEMY_GUNSHIP); + }); + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_teleport_players_on_victory_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_igb_teleport_players_on_victory_SpellScript(); + } +}; + +class achievement_im_on_a_boat : public AchievementCriteriaScript +{ + public: + achievement_im_on_a_boat() : AchievementCriteriaScript("achievement_im_on_a_boat") { } + + bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE + { + return target->GetAI() && target->GetAI()->GetData(ACTION_SHIP_VISITS) <= 2; + } +}; + +void AddSC_boss_icecrown_gunship_battle() +{ + new npc_gunship(); + new npc_high_overlord_saurfang_igb(); + new npc_muradin_bronzebeard_igb(); + new npc_zafod_boombox(); + new npc_gunship_boarding_leader(); + new npc_gunship_boarding_add(); + new npc_gunship_gunner(); + new npc_gunship_rocketeer(); + new npc_gunship_mage(); + new npc_gunship_cannon(); + new spell_igb_rocket_pack(); + new spell_igb_rocket_pack_useable(); + new spell_igb_on_gunship_deck(); + new spell_igb_periodic_trigger_with_power_cost(); + new spell_igb_cannon_blast(); + new spell_igb_incinerating_blast(); + new spell_igb_overheat(); + new spell_igb_below_zero(); + new spell_igb_teleport_to_enemy_ship(); + new spell_igb_burning_pitch_selector(); + new spell_igb_burning_pitch(); + new spell_igb_rocket_artillery(); + new spell_igb_rocket_artillery_explosion(); + new spell_igb_gunship_fall_teleport(); + new spell_igb_check_for_players(); + new spell_igb_teleport_players_on_victory(); + new achievement_im_on_a_boat(); +} diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index b678c22bf25..bcb6d746622 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -545,7 +545,7 @@ class boss_lady_deathwhisper : public CreatureScript void Summon(uint32 entry, const Position& pos) { if (TempSummon* summon = me->SummonCreature(entry, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) - summon->AI()->DoCast(summon, SPELL_TELEPORT_VISUAL); + summon->CastSpell(summon, SPELL_TELEPORT_VISUAL); } void SetGUID(uint64 guid, int32 id/* = 0*/) OVERRIDE diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index d79c6a7f8e3..888529377e9 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -539,7 +539,7 @@ class boss_the_lich_king : public CreatureScript me->VisitNearbyGridObject(333.0f, worker); // Reset any light override - SendLightOverride(0, 5000); + me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000); } bool CanAIAttack(Unit const* target) const OVERRIDE @@ -572,7 +572,7 @@ class boss_the_lich_king : public CreatureScript case ACTION_START_ENCOUNTER: instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS); Talk(SAY_LK_INTRO_1); - SendMusicToPlayers(MUSIC_FROZEN_THRONE); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FROZEN_THRONE); // schedule talks me->SetStandState(UNIT_STAND_STATE_STAND); events.ScheduleEvent(EVENT_INTRO_MOVE_1, 4000); @@ -581,10 +581,10 @@ class boss_the_lich_king : public CreatureScript events.ScheduleEvent(EVENT_START_ATTACK, 5000); break; case ACTION_PLAY_MUSIC: - SendMusicToPlayers(MUSIC_FINAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL); break; case ACTION_RESTORE_LIGHT: - SendLightOverride(0, 5000); + me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000); break; case ACTION_BREAK_FROSTMOURNE: me->CastSpell((Unit*)NULL, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS); @@ -666,7 +666,7 @@ class boss_the_lich_king : public CreatureScript events.Reset(); events.SetPhase(PHASE_OUTRO); summons.DespawnAll(); - SendMusicToPlayers(MUSIC_FURY_OF_FROSTMOURNE); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FURY_OF_FROSTMOURNE); me->InterruptNonMeleeSpells(true); me->CastSpell((Unit*)NULL, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE); me->SetWalk(true); @@ -718,8 +718,8 @@ class boss_the_lich_king : public CreatureScript { summon->CastSpell((Unit*)NULL, SPELL_BROKEN_FROSTMOURNE, true); - SendLightOverride(LIGHT_SOULSTORM, 10000); - SendWeather(WEATHER_STATE_BLACKSNOW); + me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SOULSTORM, 10000); + me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_BLACKSNOW, 0.5f); events.ScheduleEvent(EVENT_OUTRO_SOUL_BARRAGE, 5000, 0, PHASE_OUTRO); return; @@ -771,8 +771,8 @@ class boss_the_lich_king : public CreatureScript { if (spell->Id == REMORSELESS_WINTER_1 || spell->Id == REMORSELESS_WINTER_2) { - SendLightOverride(LIGHT_SNOWSTORM, 5000); - SendWeather(WEATHER_STATE_LIGHT_SNOW); + me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SNOWSTORM, 5000); + me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_LIGHT_SNOW, 0.5f); } } @@ -798,7 +798,7 @@ class boss_the_lich_king : public CreatureScript case POINT_CENTER_1: me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); - SendMusicToPlayers(MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); DoCast(me, SPELL_REMORSELESS_WINTER_1); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION); @@ -813,7 +813,7 @@ class boss_the_lich_king : public CreatureScript case POINT_CENTER_2: me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); - SendMusicToPlayers(MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); DoCast(me, SPELL_REMORSELESS_WINTER_2); summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions @@ -899,7 +899,7 @@ class boss_the_lich_king : public CreatureScript break; case EVENT_SUMMON_SHAMBLING_HORROR: DoCast(me, SPELL_SUMMON_SHAMBLING_HORROR); - SendMusicToPlayers(MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 60000, 0, PHASE_ONE); break; case EVENT_SUMMON_DRUDGE_GHOUL: @@ -959,18 +959,18 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_TWO); me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes DoCastAOE(SPELL_QUAKE); - SendMusicToPlayers(MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); Talk(SAY_LK_QUAKE); break; case EVENT_QUAKE_2: events.SetPhase(PHASE_THREE); me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes DoCastAOE(SPELL_QUAKE); - SendMusicToPlayers(MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); Talk(SAY_LK_QUAKE); break; case EVENT_SUMMON_VALKYR: - SendMusicToPlayers(MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); Talk(SAY_LK_SUMMON_VALKYR); DoCastAOE(SUMMON_VALKYR); events.ScheduleEvent(EVENT_SUMMON_VALKYR, urand(45000, 50000), 0, PHASE_TWO); @@ -981,7 +981,7 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_THREE); break; case EVENT_VILE_SPIRITS: - SendMusicToPlayers(MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); DoCastAOE(SPELL_VILE_SPIRITS); events.ScheduleEvent(EVENT_VILE_SPIRITS, urand(35000, 40000), EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); break; @@ -1052,7 +1052,7 @@ class boss_the_lich_king : public CreatureScript case EVENT_OUTRO_RAISE_DEAD: DoCastAOE(SPELL_RAISE_DEAD); me->ClearUnitState(UNIT_STATE_CASTING); - SendMusicToPlayers(MUSIC_FINAL); + me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL); break; case EVENT_OUTRO_TALK_5: Talk(SAY_LK_OUTRO_5); @@ -1093,43 +1093,6 @@ class boss_the_lich_king : public CreatureScript } private: - void SendMusicToPlayers(uint32 musicId) const - { - WorldPacket data(SMSG_PLAY_MUSIC, 4); - data << uint32(musicId); - data << uint64(me->GetGUID()); - SendPacketToPlayers(&data); - } - - void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const - { - WorldPacket data(SMSG_OVERRIDE_LIGHT, 12); - data << uint32(2488); // Light.dbc entry (map default) - data << uint32(overrideId); // Light.dbc entry (override) - data << uint32(fadeInTime); - SendPacketToPlayers(&data); - } - - void SendWeather(WeatherState weather) const - { - WorldPacket data(SMSG_WEATHER, 9); - data << uint32(weather); - data << float(0.5f); - data << uint8(0); - SendPacketToPlayers(&data); - } - - // Send packet to all players in The Frozen Throne - void SendPacketToPlayers(WorldPacket const* data) const - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (!players.isEmpty()) - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - if (Player* player = itr->GetSource()) - if (player->GetAreaId() == AREA_THE_FROZEN_THRONE) - player->GetSession()->SendPacket(data); - } - uint32 _necroticPlagueStack; uint32 _vileSpiritExplosions; }; @@ -2586,38 +2549,6 @@ class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader } }; -class spell_the_lich_king_eject_all_passengers : public SpellScriptLoader -{ - public: - spell_the_lich_king_eject_all_passengers() : SpellScriptLoader("spell_the_lich_king_eject_all_passengers") { } - - class spell_the_lich_king_eject_all_passengers_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_eject_all_passengers_SpellScript); - - bool Load() OVERRIDE - { - return GetCaster()->IsVehicle(); - } - - void HandleDummy(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetCaster()->GetVehicleKit()->RemoveAllPassengers(); - } - - void Register() OVERRIDE - { - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_eject_all_passengers_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const OVERRIDE - { - return new spell_the_lich_king_eject_all_passengers_SpellScript(); - } -}; - class spell_the_lich_king_cast_back_to_caster : public SpellScriptLoader { public: @@ -3215,7 +3146,6 @@ void AddSC_boss_the_lich_king() new spell_the_lich_king_summon_into_air(); new spell_the_lich_king_soul_reaper(); new spell_the_lich_king_valkyr_target_search(); - new spell_the_lich_king_eject_all_passengers(); new spell_the_lich_king_cast_back_to_caster(); new spell_the_lich_king_life_siphon(); new spell_the_lich_king_vile_spirits(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 8e529ba0ee9..6aeab015b78 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -68,7 +68,7 @@ enum TeleporterSpells DEATHBRINGER_S_RISE_TELEPORT = 70858, UPPER_SPIRE_TELEPORT = 70859, FROZEN_THRONE_TELEPORT = 70860, - SINDRAGOSA_S_LAIR_TELEPORT = 70861, + SINDRAGOSA_S_LAIR_TELEPORT = 70861 }; enum DataTypes @@ -76,7 +76,7 @@ enum DataTypes // Encounter States/Boss GUIDs DATA_LORD_MARROWGAR = 0, DATA_LADY_DEATHWHISPER = 1, - DATA_GUNSHIP_EVENT = 2, + DATA_ICECROWN_GUNSHIP_BATTLE = 2, DATA_DEATHBRINGER_SAURFANG = 3, DATA_FESTERGUT = 4, DATA_ROTFACE = 5, @@ -116,6 +116,7 @@ enum DataTypes DATA_HIGHLORD_TIRION_FORDRING = 37, DATA_ARTHAS_PLATFORM = 38, DATA_TERENAS_MENETHIL = 39, + DATA_ENEMY_GUNSHIP = 40 }; enum CreaturesIds @@ -169,6 +170,33 @@ enum CreaturesIds NPC_REANIMATED_ADHERENT = 38010, NPC_VENGEFUL_SHADE = 38222, + // Icecrown Gunship Battle + NPC_MARTYR_STALKER_IGB_SAURFANG = 38569, + NPC_ALLIANCE_GUNSHIP_CANNON = 36838, + NPC_HORDE_GUNSHIP_CANNON = 36839, + NPC_SKYBREAKER_DECKHAND = 36970, + NPC_ORGRIMS_HAMMER_CREW = 36971, + NPC_IGB_HIGH_OVERLORD_SAURFANG = 36939, + NPC_IGB_MURADIN_BRONZEBEARD = 36948, + NPC_THE_SKYBREAKER = 37540, + NPC_ORGRIMS_HAMMER = 37215, + NPC_GUNSHIP_HULL = 37547, + NPC_TELEPORT_PORTAL = 37227, + NPC_TELEPORT_EXIT = 37488, + NPC_SKYBREAKER_SORCERER = 37116, + NPC_SKYBREAKER_RIFLEMAN = 36969, + NPC_SKYBREAKER_MORTAR_SOLDIER = 36978, + NPC_SKYBREAKER_MARINE = 36950, + NPC_SKYBREAKER_SERGEANT = 36961, + NPC_KOR_KRON_BATTLE_MAGE = 37117, + NPC_KOR_KRON_AXETHROWER = 36968, + NPC_KOR_KRON_ROCKETEER = 36982, + NPC_KOR_KRON_REAVER = 36957, + NPC_KOR_KRON_SERGEANT = 36960, + NPC_ZAFOD_BOOMBOX = 37184, + NPC_HIGH_CAPTAIN_JUSTIN_BARTLETT = 37182, + NPC_SKY_REAVER_KORM_BLACKSCAR = 37833, + // Deathbringer Saurfang NPC_DEATHBRINGER_SAURFANG = 37813, NPC_BLOOD_BEAST = 38508, @@ -285,7 +313,7 @@ enum CreaturesIds NPC_FROSTMOURNE_TRIGGER = 38584, // Generic - NPC_INVISIBLE_STALKER = 30298, + NPC_INVISIBLE_STALKER = 30298 }; enum GameObjectsIds @@ -305,6 +333,22 @@ enum GameObjectsIds GO_ORATORY_OF_THE_DAMNED_ENTRANCE = 201563, GO_LADY_DEATHWHISPER_ELEVATOR = 202220, + // Icecrown Gunship Battle - Horde raid + GO_ORGRIMS_HAMMER_H = 201812, + GO_THE_SKYBREAKER_H = 201811, + GO_GUNSHIP_ARMORY_H_10N = 202178, + GO_GUNSHIP_ARMORY_H_25N = 202180, + GO_GUNSHIP_ARMORY_H_10H = 202177, + GO_GUNSHIP_ARMORY_H_25H = 202179, + + // Icecrown Gunship Battle - Alliance raid + GO_ORGRIMS_HAMMER_A = 201581, + GO_THE_SKYBREAKER_A = 201580, + GO_GUNSHIP_ARMORY_A_10N = 201873, + GO_GUNSHIP_ARMORY_A_25N = 201874, + GO_GUNSHIP_ARMORY_A_10H = 201872, + GO_GUNSHIP_ARMORY_A_25H = 201875, + // Deathbringer Saurfang GO_SAURFANG_S_DOOR = 201825, GO_DEATHBRINGER_S_CACHE_10N = 202239, @@ -368,7 +412,7 @@ enum GameObjectsIds GO_DOODAD_ICECROWN_SNOWEDGEWARNING01 = 202190, GO_FROZEN_LAVAMAN = 202436, GO_LAVAMAN_PILLARS_CHAINED = 202437, - GO_LAVAMAN_PILLARS_UNCHAINED = 202438, + GO_LAVAMAN_PILLARS_UNCHAINED = 202438 }; enum AchievementCriteriaIds @@ -403,11 +447,15 @@ enum AchievementCriteriaIds CRITERIA_ONCE_BITTEN_TWICE_SHY_10N = 12780, CRITERIA_ONCE_BITTEN_TWICE_SHY_25N = 13012, CRITERIA_ONCE_BITTEN_TWICE_SHY_10V = 13011, - CRITERIA_ONCE_BITTEN_TWICE_SHY_25V = 13013, + CRITERIA_ONCE_BITTEN_TWICE_SHY_25V = 13013 }; enum SharedActions { + // Icecrown Gunship Battle + ACTION_ENEMY_GUNSHIP_TALK = -369390, + ACTION_EXIT_SHIP = -369391, + // Festergut ACTION_FESTERGUT_COMBAT = -366260, ACTION_FESTERGUT_GAS = -366261, @@ -431,7 +479,7 @@ enum SharedActions // The Lich King ACTION_RESTORE_LIGHT = -72262, - ACTION_FROSTMOURNE_INTRO = -36823, + ACTION_FROSTMOURNE_INTRO = -36823 }; enum WeekliesICC @@ -445,7 +493,7 @@ enum WeekliesICC QUEST_BLOOD_QUICKENING_10 = 24874, QUEST_BLOOD_QUICKENING_25 = 24879, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10 = 24872, - QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25 = 24880, + QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25 = 24880 }; enum WorldStatesICC @@ -454,12 +502,13 @@ enum WorldStatesICC WORLDSTATE_EXECUTION_TIME = 4904, WORLDSTATE_SHOW_ATTEMPTS = 4940, WORLDSTATE_ATTEMPTS_REMAINING = 4941, - WORLDSTATE_ATTEMPTS_MAX = 4942, + WORLDSTATE_ATTEMPTS_MAX = 4942 }; enum AreaIds { - AREA_THE_FROZEN_THRONE = 4859, + AREA_ICECROWN_CITADEL = 4812, + AREA_THE_FROZEN_THRONE = 4859 }; class spell_trigger_spell_from_caster : public SpellScriptLoader diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp index ad06bc1c485..b56e0dd6360 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp @@ -38,7 +38,7 @@ class icecrown_citadel_teleport : public GameObjectScript player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Oratory of the Damned.", GOSSIP_SENDER_ICC_PORT, ORATORY_OF_THE_DAMNED_TELEPORT); if (instance->GetBossState(DATA_LADY_DEATHWHISPER) == DONE) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Rampart of Skulls.", GOSSIP_SENDER_ICC_PORT, RAMPART_OF_SKULLS_TELEPORT); - if (instance->GetBossState(DATA_GUNSHIP_EVENT) == DONE) + if (instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == DONE) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Deathbringer's Rise.", GOSSIP_SENDER_ICC_PORT, DEATHBRINGER_S_RISE_TELEPORT); if (instance->GetData(DATA_COLDFLAME_JETS) == DONE) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Upper Spire.", GOSSIP_SENDER_ICC_PORT, UPPER_SPIRE_TELEPORT); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index f110f04f16c..51de8a1fe23 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -15,23 +15,30 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ObjectMgr.h" -#include "ScriptMgr.h" +#include "AccountMgr.h" #include "InstanceScript.h" -#include "ScriptedCreature.h" #include "Map.h" -#include "PoolMgr.h" -#include "AccountMgr.h" -#include "icecrown_citadel.h" +#include "ObjectMgr.h" #include "Player.h" +#include "PoolMgr.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "Transport.h" +#include "TransportMgr.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "icecrown_citadel.h" enum EventIds { + EVENT_PLAYERS_GUNSHIP_SPAWN = 22663, + EVENT_PLAYERS_GUNSHIP_COMBAT = 22664, + EVENT_PLAYERS_GUNSHIP_SAURFANG = 22665, + EVENT_ENEMY_GUNSHIP_COMBAT = 22860, + EVENT_ENEMY_GUNSHIP_DESPAWN = 22861, EVENT_QUAKE = 23437, EVENT_SECOND_REMORSELESS_WINTER = 23507, - EVENT_TELEPORT_TO_FROSMOURNE = 23617, + EVENT_TELEPORT_TO_FROSTMOURNE = 23617 }; enum TimedEvents @@ -39,6 +46,7 @@ enum TimedEvents EVENT_UPDATE_EXECUTION_TIME = 1, EVENT_QUAKE_SHATTER = 2, EVENT_REBUILD_PLATFORM = 3, + EVENT_RESPAWN_GUNSHIP = 4 }; DoorData const doorData[] = @@ -68,7 +76,7 @@ DoorData const doorData[] = {GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SE }, {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SW }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE}, // END + {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END }; // this doesnt have to only store questgivers, also can be used for related quest spawns @@ -89,7 +97,7 @@ WeeklyQuest const WeeklyQuestData[WeeklyNPCs] = {NPC_ALRIN_THE_AGILE, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening {NPC_INFILTRATOR_MINCHAR_BQ, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening {NPC_MINCHAR_BEAM_STALKER, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening - {NPC_VALITHRIA_DREAMWALKER_QUEST, {QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25}}, // Respite for a Tormented Soul + {NPC_VALITHRIA_DREAMWALKER_QUEST, {QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25}} // Respite for a Tormented Soul }; class instance_icecrown_citadel : public InstanceMapScript @@ -106,6 +114,9 @@ class instance_icecrown_citadel : public InstanceMapScript TeamInInstance = 0; HeroicAttempts = MaxHeroicAttempts; LadyDeathwisperElevatorGUID = 0; + GunshipGUID = 0; + EnemyGunshipGUID = 0; + GunshipArmoryGUID = 0; DeathbringerSaurfangGUID = 0; DeathbringerSaurfangDoorGUID = 0; DeathbringerSaurfangEventGUID = 0; @@ -164,6 +175,9 @@ class instance_icecrown_citadel : public InstanceMapScript { if (!TeamInInstance) TeamInInstance = player->GetTeam(); + + if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE) + SpawnGunship(); } void OnCreatureCreate(Creature* creature) OVERRIDE @@ -217,6 +231,10 @@ class instance_icecrown_citadel : public InstanceMapScript case NPC_DEATHBRINGER_SAURFANG: DeathbringerSaurfangGUID = creature->GetGUID(); break; + case NPC_ALLIANCE_GUNSHIP_CANNON: + case NPC_HORDE_GUNSHIP_CANNON: + creature->SetControlled(true, UNIT_STATE_ROOT); + break; case NPC_SE_HIGH_OVERLORD_SAURFANG: if (TeamInInstance == ALLIANCE) creature->UpdateEntry(NPC_SE_MURADIN_BRONZEBEARD, ALLIANCE, creature->GetCreatureData()); @@ -335,12 +353,60 @@ class instance_icecrown_citadel : public InstanceMapScript { uint8 diffIndex = uint8(instance->GetSpawnMode() & 1); if (!sPoolMgr->IsSpawnedObject<Quest>(WeeklyQuestData[questIndex].questId[diffIndex])) - entry = 0; + return 0; break; } } break; } + case NPC_HORDE_GUNSHIP_CANNON: + case NPC_ORGRIMS_HAMMER_CREW: + case NPC_SKY_REAVER_KORM_BLACKSCAR: + if (TeamInInstance == ALLIANCE) + return 0; + break; + case NPC_ALLIANCE_GUNSHIP_CANNON: + case NPC_SKYBREAKER_DECKHAND: + case NPC_HIGH_CAPTAIN_JUSTIN_BARTLETT: + if (TeamInInstance == HORDE) + return 0; + break; + case NPC_ZAFOD_BOOMBOX: + if (GameObjectTemplate const* go = sObjectMgr->GetGameObjectTemplate(GO_THE_SKYBREAKER_A)) + if ((TeamInInstance == ALLIANCE && data->mapid == go->moTransport.mapID) || + (TeamInInstance == HORDE && data->mapid != go->moTransport.mapID)) + return entry; + return 0; + case NPC_IGB_MURADIN_BRONZEBEARD: + if ((TeamInInstance == ALLIANCE && data->posX > 10.0f) || + (TeamInInstance == HORDE && data->posX < 10.0f)) + return entry; + return 0; + default: + break; + } + + return entry; + } + + uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) OVERRIDE + { + switch (entry) + { + case GO_GUNSHIP_ARMORY_H_10N: + case GO_GUNSHIP_ARMORY_H_25N: + case GO_GUNSHIP_ARMORY_H_10H: + case GO_GUNSHIP_ARMORY_H_25H: + if (TeamInInstance == ALLIANCE) + return 0; + break; + case GO_GUNSHIP_ARMORY_A_10N: + case GO_GUNSHIP_ARMORY_A_25N: + case GO_GUNSHIP_ARMORY_A_10H: + case GO_GUNSHIP_ARMORY_A_25H: + if (TeamInInstance == HORDE) + return 0; + break; default: break; } @@ -446,6 +512,20 @@ class instance_icecrown_citadel : public InstanceMapScript go->SetGoState(GO_STATE_READY); } break; + case GO_THE_SKYBREAKER_H: + case GO_ORGRIMS_HAMMER_A: + EnemyGunshipGUID = go->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_H_10N: + case GO_GUNSHIP_ARMORY_H_25N: + case GO_GUNSHIP_ARMORY_H_10H: + case GO_GUNSHIP_ARMORY_H_25H: + case GO_GUNSHIP_ARMORY_A_10N: + case GO_GUNSHIP_ARMORY_A_25N: + case GO_GUNSHIP_ARMORY_A_10H: + case GO_GUNSHIP_ARMORY_A_25H: + GunshipArmoryGUID = go->GetGUID(); + break; case GO_SAURFANG_S_DOOR: DeathbringerSaurfangDoorGUID = go->GetGUID(); AddDoor(go, true); @@ -583,6 +663,10 @@ class instance_icecrown_citadel : public InstanceMapScript case GO_ICE_WALL: AddDoor(go, false); break; + case GO_THE_SKYBREAKER_A: + case GO_ORGRIMS_HAMMER_H: + GunshipGUID = 0; + break; default: break; } @@ -617,6 +701,10 @@ class instance_icecrown_citadel : public InstanceMapScript { switch (type) { + case DATA_ICECROWN_GUNSHIP_BATTLE: + return GunshipGUID; + case DATA_ENEMY_GUNSHIP: + return EnemyGunshipGUID; case DATA_DEATHBRINGER_SAURFANG: return DeathbringerSaurfangGUID; case DATA_SAURFANG_EVENT_NPC: @@ -687,7 +775,7 @@ class instance_icecrown_citadel : public InstanceMapScript switch (type) { case DATA_LADY_DEATHWHISPER: - SetBossState(DATA_GUNSHIP_EVENT, state); // TEMP HACK UNTIL GUNSHIP SCRIPTED + { if (state == DONE) { if (GameObject* elevator = instance->GetGameObject(LadyDeathwisperElevatorGUID)) @@ -695,7 +783,19 @@ class instance_icecrown_citadel : public InstanceMapScript elevator->SetUInt32Value(GAMEOBJECT_LEVEL, 0); elevator->SetGoState(GO_STATE_READY); } + + SpawnGunship(); + } + break; + } + case DATA_ICECROWN_GUNSHIP_BATTLE: + if (state == DONE) + { + if (GameObject* loot = instance->GetGameObject(GunshipArmoryGUID)) + loot->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE | GO_FLAG_NODESPAWN); } + else if (state == FAIL) + Events.ScheduleEvent(EVENT_RESPAWN_GUNSHIP, 30000); break; case DATA_DEATHBRINGER_SAURFANG: switch (state) @@ -842,6 +942,17 @@ class instance_icecrown_citadel : public InstanceMapScript return true; } + void SpawnGunship() + { + if (!GunshipGUID) + { + SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, NOT_STARTED); + uint32 gunshipEntry = TeamInInstance == HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A; + if (Transport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance)) + GunshipGUID = gunship->GetGUID(); + } + } + void SetData(uint32 type, uint32 data) OVERRIDE { switch (type) @@ -1062,10 +1173,10 @@ class instance_icecrown_citadel : public InstanceMapScript return false; // no break case DATA_DEATHBRINGER_SAURFANG: - if (GetBossState(DATA_GUNSHIP_EVENT) != DONE) + if (GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE) return false; // no break - case DATA_GUNSHIP_EVENT: + case DATA_ICECROWN_GUNSHIP_BATTLE: if (GetBossState(DATA_LADY_DEATHWHISPER) != DONE) return false; // no break @@ -1159,7 +1270,7 @@ class instance_icecrown_citadel : public InstanceMapScript void Update(uint32 diff) OVERRIDE { - if (BloodQuickeningState != IN_PROGRESS && GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS) + if (BloodQuickeningState != IN_PROGRESS && GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != FAIL) return; Events.Update(diff); @@ -1209,16 +1320,42 @@ class instance_icecrown_citadel : public InstanceMapScript if (GameObject* wind = instance->GetGameObject(FrozenThroneWindGUID)) wind->SetGoState(GO_STATE_ACTIVE); break; + case EVENT_RESPAWN_GUNSHIP: + SpawnGunship(); + break; default: break; } } } - void ProcessEvent(WorldObject* /*source*/, uint32 eventId) OVERRIDE + void ProcessEvent(WorldObject* source, uint32 eventId) OVERRIDE { switch (eventId) { + case EVENT_ENEMY_GUNSHIP_DESPAWN: + if (GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == DONE) + source->AddObjectToRemoveList(); + break; + case EVENT_ENEMY_GUNSHIP_COMBAT: + if (Creature* captain = source->FindNearestCreature(TeamInInstance == HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 100.0f)) + captain->AI()->DoAction(ACTION_ENEMY_GUNSHIP_TALK); + // no break; + case EVENT_PLAYERS_GUNSHIP_SPAWN: + case EVENT_PLAYERS_GUNSHIP_COMBAT: + if (GameObject* go = source->ToGameObject()) + if (Transport* transport = go->ToTransport()) + transport->EnableMovement(false); + break; + case EVENT_PLAYERS_GUNSHIP_SAURFANG: + { + if (Creature* captain = source->FindNearestCreature(TeamInInstance == HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 100.0f)) + captain->AI()->DoAction(ACTION_EXIT_SHIP); + if (GameObject* go = source->ToGameObject()) + if (Transport* transport = go->ToTransport()) + transport->EnableMovement(false); + break; + } case EVENT_QUAKE: if (GameObject* warning = instance->GetGameObject(FrozenThroneWarningGUID)) warning->SetGoState(GO_STATE_ACTIVE); @@ -1231,7 +1368,7 @@ class instance_icecrown_citadel : public InstanceMapScript Events.ScheduleEvent(EVENT_REBUILD_PLATFORM, 1500); } break; - case EVENT_TELEPORT_TO_FROSMOURNE: // Harvest Soul (normal mode) + case EVENT_TELEPORT_TO_FROSTMOURNE: // Harvest Soul (normal mode) if (Creature* terenas = instance->SummonCreature(NPC_TERENAS_MENETHIL_FROSTMOURNE, TerenasSpawn, NULL, 63000)) { terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO); @@ -1257,6 +1394,9 @@ class instance_icecrown_citadel : public InstanceMapScript protected: EventMap Events; uint64 LadyDeathwisperElevatorGUID; + uint64 GunshipGUID; + uint64 EnemyGunshipGUID; + uint64 GunshipArmoryGUID; uint64 DeathbringerSaurfangGUID; uint64 DeathbringerSaurfangDoorGUID; uint64 DeathbringerSaurfangEventGUID; // Muradin Bronzebeard or High Overlord Saurfang diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 58f8943fae6..568119d01ad 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -469,6 +469,7 @@ public: DoCast(me, SPELL_VORTEX_3, true); break; case ACTION_LIFT_IN_AIR: + { Position _zToLift; me->GetPosition(&_zToLift); if (_phase == PHASE_ONE) @@ -482,6 +483,7 @@ public: me->GetMotionMaster()->MoveTakeoff(POINT_PHASE_ONE_TO_TWO_TRANSITION, _zToLift); } break; + } case ACTION_HANDLE_P_THREE_INTRO: events.CancelEventGroup(0); events.CancelEventGroup(1); @@ -544,7 +546,7 @@ public: break; case PHASE_TWO: events.ScheduleEvent(EVENT_MOVE_TO_POINT_SURGE_P_TWO, 60*IN_MILLISECONDS, 0, _phase); - me->AI()->DoAction(ACTION_LIFT_IN_AIR); + DoAction(ACTION_LIFT_IN_AIR); break; case PHASE_THREE: events.ScheduleEvent(EVENT_ARCANE_PULSE, 7*IN_MILLISECONDS, 0, _phase); @@ -584,7 +586,7 @@ public: { instance->SetBossState(DATA_MALYGOS_EVENT, FAIL); - SendLightOverride(LIGHT_GET_DEFAULT_FOR_MAP, 1*IN_MILLISECONDS); + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_GET_DEFAULT_FOR_MAP, 1*IN_MILLISECONDS); if (_phase == PHASE_THREE) me->SetControlled(false, UNIT_STATE_ROOT); @@ -725,8 +727,8 @@ public: me->SetDisableGravity(true); if (Creature* alexstraszaBunny = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) me->SetFacingToObject(alexstraszaBunny); - SendLightOverride(LIGHT_ARCANE_RUNES, 5*IN_MILLISECONDS); - events.ScheduleEvent(EVENT_FLY_OUT_OF_PLATFORM, 18*IN_MILLISECONDS, 0, PHASE_TWO); + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_ARCANE_RUNES, 5 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_FLY_OUT_OF_PLATFORM, 18 * IN_MILLISECONDS, 0, PHASE_TWO); break; case POINT_SURGE_OF_POWER_P_TWO: if (!_performingDestroyPlatform) @@ -737,7 +739,7 @@ public: } break; case POINT_DESTROY_PLATFORM_P_TWO: - SendLightOverride(LIGHT_OBSCURE_SPACE, 1*IN_MILLISECONDS); + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_SPACE, 1 * IN_MILLISECONDS); DoCast(me, SPELL_DESTROY_PLATFORM_CHANNEL); events.ScheduleEvent(EVENT_MOVE_TO_P_THREE_POINT, 11*IN_MILLISECONDS, 0, PHASE_TWO); break; @@ -929,7 +931,7 @@ public: } break; case EVENT_LIGHT_DIMENSION_CHANGE: - SendLightOverride(LIGHT_CHANGE_DIMENSIONS, 2*IN_MILLISECONDS); + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_CHANGE_DIMENSIONS, 2 * IN_MILLISECONDS); break; case EVENT_DELAY_MOVE_TO_DESTROY_P: me->GetMotionMaster()->MovePoint(POINT_DESTROY_PLATFORM_P_TWO, MalygosPositions[0]); @@ -939,7 +941,7 @@ public: me->GetMotionMaster()->MovePoint(POINT_IDLE_P_THREE, MalygosPositions[4]); break; case EVENT_START_P_THREE: - SendLightOverride(LIGHT_OBSCURE_ARCANE_RUNES, 1*IN_MILLISECONDS); + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_ARCANE_RUNES, 1 * IN_MILLISECONDS); DoCast(me, SPELL_CLEAR_ALL_DEBUFFS); DoCast(me, SPELL_IMMUNE_CURSES); _canAttack = true; @@ -1026,27 +1028,6 @@ public: } } - // Function that will change lights of map for all players on map. - void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const - { - WorldPacket data(SMSG_OVERRIDE_LIGHT, 12); - data << uint32(1773); // Light.dbc entry (map default) - data << uint32(overrideId); // Light.dbc entry (override) - data << uint32(fadeInTime); - SendPacketToPlayers(&data); - } - - // Send packet to all players in Eye of Eternity - void SendPacketToPlayers(WorldPacket const* data) const - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (!players.isEmpty()) - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - if (Player* player = itr->GetSource()) - if (player->GetAreaId() == AREA_EYE_OF_ETERNITY) - player->GetSession()->SendPacket(data); - } - uint8 _phase; // Counter for phases used with a getter. uint8 _summonDeaths; // Keeps count of arcane trash. uint8 _preparingPulsesChecker; // In retail they use 2 preparing pulses with 7 sec CD, after they pass 2 seconds. @@ -2346,7 +2327,7 @@ class spell_malygos_surge_of_power_warning_selector_25 : public SpellScriptLoade void ExecuteMainSpell() { - GetCaster()->ToCreature()->AI()->DoCastAOE(SPELL_SURGE_OF_POWER_PHASE_3_25); + GetCaster()->ToCreature()->CastSpell((Unit*)NULL, SPELL_SURGE_OF_POWER_PHASE_3_25); } void Register() OVERRIDE diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp index cfa1b704c90..ee1524564a8 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp @@ -199,17 +199,17 @@ public: if (summon->GetGUID() == uiFireMagusGUID) { - me->AI()->DoAction(ACTION_MAGUS_DEAD); + DoAction(ACTION_MAGUS_DEAD); bFireMagusDead = true; } else if (summon->GetGUID() == uiFrostMagusGUID) { - me->AI()->DoAction(ACTION_MAGUS_DEAD); + DoAction(ACTION_MAGUS_DEAD); bFrostMagusDead = true; } else if (summon->GetGUID() == uiArcaneMagusGUID) { - me->AI()->DoAction(ACTION_MAGUS_DEAD); + DoAction(ACTION_MAGUS_DEAD); bArcaneMagusDead = true; } } diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index 2c809b17367..39dec9999cc 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -208,9 +208,11 @@ class instance_oculus : public InstanceMapScript break; case DATA_VAROS: if (state == DONE) + { DoUpdateWorldState(WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW, 0); if (Creature* urom = instance->GetCreature(UromGUID)) urom->SetPhaseMask(1, true); + } break; case DATA_UROM: if (state == DONE) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 9599700eccb..e2c6a72241e 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -652,7 +652,6 @@ class boss_algalon_the_observer : public CreatureScript break; case EVENT_OUTRO_2: _EnterEvadeMode(); - me->AddUnitState(UNIT_STATE_EVADE); me->GetMotionMaster()->MovePoint(POINT_ALGALON_OUTRO, AlgalonOutroPos); break; case EVENT_OUTRO_3: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp index 5b43e8d1bf6..cfedb9bce31 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp @@ -364,7 +364,7 @@ class npc_sanctum_sentry : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { me->AddThreat(target, 100.0f); - me->AI()->AttackStart(target); + AttackStart(target); DoCast(target, SPELL_SAVAGE_POUNCE); } events.ScheduleEvent(EVENT_POUNCE, urand(12000, 17000)); @@ -430,7 +430,7 @@ class npc_feral_defender : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { me->AddThreat(target, 100.0f); - me->AI()->AttackStart(target); + AttackStart(target); DoCast(target, SPELL_FERAL_POUNCE); } events.ScheduleEvent(EVENT_FERAL_POUNCE, urand(10000, 12000)); @@ -439,7 +439,7 @@ class npc_feral_defender : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { me->AddThreat(target, 100.0f); - me->AI()->AttackStart(target); + AttackStart(target); DoCast(target, SPELL_FERAL_RUSH); } events.ScheduleEvent(EVENT_RUSH, urand(10000, 12000)); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 96840842d24..5c51f0fe2c8 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -589,17 +589,19 @@ class boss_flame_leviathan_seat : public CreatureScript else if (Creature* leviathan = me->GetVehicleCreatureBase()) leviathan->AI()->Talk(SAY_PLAYER_RIDING); - if (Creature* turret = me->GetVehicleKit()->GetPassenger(SEAT_TURRET)->ToCreature()) - { - turret->setFaction(me->GetVehicleBase()->getFaction()); - turret->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable - turret->AI()->AttackStart(who); - } - if (Creature* device = me->GetVehicleKit()->GetPassenger(SEAT_DEVICE)->ToCreature()) - { - device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - device->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } + if (Unit* turretPassenger = me->GetVehicleKit()->GetPassenger(SEAT_TURRET)) + if (Creature* turret = turretPassenger->ToCreature()) + { + turret->setFaction(me->GetVehicleBase()->getFaction()); + turret->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable + turret->AI()->AttackStart(who); + } + if (Unit* devicePassenger = me->GetVehicleKit()->GetPassenger(SEAT_DEVICE)) + if (Creature* device = devicePassenger->ToCreature()) + { + device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + device->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 64ee385b7fc..7f3e6485eaf 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -1069,7 +1069,7 @@ class npc_detonating_lasher : public CreatureScript { // Switching to other target - modify aggro of new target by 20% from current target's aggro me->AddThreat(target, me->getThreatManager().getThreat(me->GetVictim(), false) * 1.2f); - me->AI()->AttackStart(target); + AttackStart(target); } changeTargetTimer = urand(5000, 10000); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 169a7085672..578a51fa1f8 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -455,7 +455,7 @@ class boss_hodir : public CreatureScript if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) if (Aura* BitingColdAura = target->GetAura(SPELL_BITING_COLD_TRIGGERED)) if ((target->GetTypeId() == TYPEID_PLAYER) && (BitingColdAura->GetStackAmount() > 2)) - me->AI()->SetData(DATA_GETTING_COLD_IN_HERE, 0); + SetData(DATA_GETTING_COLD_IN_HERE, 0); gettingColdInHereTimer = 1000; } else diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index e96cfaccc56..d1ed15bf8dd 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -211,8 +211,8 @@ class boss_razorscale_controller : public CreatureScript Harpoon3->RemoveFromWorld(); if (GameObject* Harpoon4 = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_RAZOR_HARPOON_4))) Harpoon4->RemoveFromWorld(); - me->AI()->DoAction(ACTION_HARPOON_BUILD); - me->AI()->DoAction(ACTION_PLACE_BROKEN_HARPOON); + DoAction(ACTION_HARPOON_BUILD); + DoAction(ACTION_PLACE_BROKEN_HARPOON); break; case SPELL_HARPOON_SHOT_1: case SPELL_HARPOON_SHOT_2: diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index b6438008dde..e9cf806118f 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -291,7 +291,7 @@ public: m_uiCrushTimer = 8000; m_uiPoisonedSpearTimer = 10000; m_uiWhirlwindTimer = 20000; - me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); + AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); } } } diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp index 6835228ca46..746680e32e6 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp @@ -189,7 +189,7 @@ public: void JustSummoned(Creature* summon) OVERRIDE { summon->AI()->AttackStart(me->GetVictim()); - summon->AI()->DoCastAOE(SPELL_ZURAMAT_ADD_2); + summon->CastSpell((Unit*)NULL, SPELL_ZURAMAT_ADD_2); summon->SetPhaseMask(17, true); } }; diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index f840c0562b3..6ea4490c79d 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -44,6 +44,7 @@ EndContentData */ #include "Player.h" #include "SpellInfo.h" #include "WorldSession.h" +#include "SpellScript.h" /*###### ## npc_sinkhole_kill_credit @@ -2414,7 +2415,7 @@ public: { me->setFaction(14); if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) - me->AI()->AttackStart(player); + AttackStart(player); } void UpdateAI(uint32 uiDiff) OVERRIDE @@ -2537,6 +2538,39 @@ public: }; +enum WindsoulTotemAura +{ + SPELL_WINDSOUL_CREDT = 46378 +}; + +class spell_windsoul_totem_aura : public SpellScriptLoader +{ +public: + spell_windsoul_totem_aura() : SpellScriptLoader("spell_windsoul_totem_aura") { } + + class spell_windsoul_totem_aura_AuraScript : public AuraScript + { + PrepareAuraScript(spell_windsoul_totem_aura_AuraScript); + + void OnRemove(AuraEffect const*, AuraEffectHandleModes) + { + if (GetTarget()->isDead()) + if (Unit* caster = GetCaster()) + caster->CastSpell(NULL, SPELL_WINDSOUL_CREDT); + } + + void Register() OVERRIDE + { + OnEffectRemove += AuraEffectRemoveFn(spell_windsoul_totem_aura_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_windsoul_totem_aura_AuraScript(); + } +}; + void AddSC_borean_tundra() { new npc_sinkhole_kill_credit(); @@ -2565,4 +2599,5 @@ void AddSC_borean_tundra() new npc_valiance_keep_cannoneer(); new npc_warmage_coldarra(); new npc_hidden_cultist(); + new spell_windsoul_totem_aura(); } diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index 7487c3c8828..a9c46d19138 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -654,6 +654,7 @@ class npc_torturer_lecraft : public CreatureScript { npc_torturer_lecraftAI(Creature* creature) : ScriptedAI(creature) { + _textCounter = 1; _playerGUID = 0; } diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp index 798801041f4..fd51237745e 100644 --- a/src/server/scripts/Northrend/zone_howling_fjord.cpp +++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp @@ -458,10 +458,10 @@ class spell_mindless_abomination_explosion_fx_master : public SpellScriptLoader if (!caster) return; - caster->AI()->DoCast(caster, SPELL_COSMETIC_BLOOD_EXPLOSION_GREEN_LARGE); + caster->CastSpell(caster, SPELL_COSMETIC_BLOOD_EXPLOSION_GREEN_LARGE); for (uint8 i = 0; i < 10; ++i) - caster->AI()->DoCast(caster, SPELL_RANDOM_CIRCUMFERENCE_POINT_POISON); + caster->CastSpell(caster, SPELL_RANDOM_CIRCUMFERENCE_POINT_POISON); caster->DespawnOrUnsummon(4000); } diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index f7894c58b3e..5284803c5f2 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -527,7 +527,7 @@ public: { me->setRegeneratingHealth(false); DoCast(SPELL_THREAT_PULSE); - me->AI()->Talk(BANNER_SAY); + Talk(BANNER_SAY); events.ScheduleEvent(EVENT_SPAWN, 3000); } diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index 0298500e790..6e39d341c58 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -1003,7 +1003,7 @@ enum ReconnaissanceFlight VIC_SAY_6 = 6, PLANE_EMOTE = 0, - AURA_ENGINE = 52255, // Engine on Fire + SPELL_ENGINE = 52255, // Engine on Fire SPELL_LAND = 52226, // Land Flying Machine SPELL_CREDIT = 53328 // Land Flying Machine Credit @@ -1054,8 +1054,8 @@ public: pilot->AI()->Talk(VIC_SAY_6); break; case 25: - me->AI()->Talk(PLANE_EMOTE); - me->AI()->DoCast(AURA_ENGINE); + Talk(PLANE_EMOTE); + DoCast(SPELL_ENGINE); break; } } diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index 70de4d4758d..838fa44ded4 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -290,22 +290,23 @@ public: events.ScheduleEvent(EVENT_CHECK_AREA, 5000); break; case EVENT_REACHED_HOME: - Unit* player = me->GetVehicleKit()->GetPassenger(0); - if (player && player->GetTypeId() == TYPEID_PLAYER) - { - // for each prisoner on drake, give credit - for (uint8 i = 1; i < 4; ++i) - if (Unit* prisoner = me->GetVehicleKit()->GetPassenger(i)) + if (Vehicle* vehicle = me->GetVehicleKit()) + if (Unit* player = vehicle->GetPassenger(0)) + if (player->GetTypeId() == TYPEID_PLAYER) { - if (prisoner->GetTypeId() != TYPEID_UNIT) - return; - prisoner->CastSpell(player, SPELL_KILL_CREDIT_PRISONER, true); - prisoner->CastSpell(prisoner, SPELL_SUMMON_LIBERATED, true); - prisoner->ExitVehicle(); + // for each prisoner on drake, give credit + for (uint8 i = 1; i < 4; ++i) + if (Unit* prisoner = me->GetVehicleKit()->GetPassenger(i)) + { + if (prisoner->GetTypeId() != TYPEID_UNIT) + return; + prisoner->CastSpell(player, SPELL_KILL_CREDIT_PRISONER, true); + prisoner->CastSpell(prisoner, SPELL_SUMMON_LIBERATED, true); + prisoner->ExitVehicle(); + } + me->CastSpell(me, SPELL_KILL_CREDIT_DRAKE, true); + player->ExitVehicle(); } - me->CastSpell(me, SPELL_KILL_CREDIT_DRAKE, true); - player->ExitVehicle(); - } break; } } @@ -453,6 +454,9 @@ public: { npc_brann_bronzebeard_keystoneAI(Creature* creature) : ScriptedAI(creature) { + memset(&objectGUID, 0, sizeof(objectGUID)); + playerGUID = 0; + voiceGUID = 0; objectCounter = 0; } @@ -500,7 +504,7 @@ public: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID)) { - voice->AI()->DoCast(voice, SPELL_RESURRECTION); + voice->CastSpell(voice, SPELL_RESURRECTION); if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) voice->AI()->Talk(SAY_VOICE_1, player); } @@ -542,7 +546,7 @@ public: break; case EVENT_SCRIPT_9: if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID)) - voice->AI()->DoCast(voice, SPELL_RESURRECTION); + voice->CastSpell(voice, SPELL_RESURRECTION); events.ScheduleEvent(EVENT_SCRIPT_10, 6000); break; case EVENT_SCRIPT_10: @@ -639,6 +643,7 @@ public: { npc_king_jokkum_vehicleAI(Creature* creature) : VehicleAI(creature) { + playerGUID = 0; pathEnd = false; } @@ -787,37 +792,6 @@ class spell_veranus_summon : public SpellScriptLoader } }; -/*##### -# spell_jokkum_eject_all -#####*/ - -class spell_jokkum_eject_all : public SpellScriptLoader -{ - public: spell_jokkum_eject_all() : SpellScriptLoader("spell_jokkum_eject_all") { } - - class spell_jokkum_eject_all_SpellScript : public SpellScript - { - PrepareSpellScript(spell_jokkum_eject_all_SpellScript); - - void HandleScriptEffect(SpellEffIndex /* effIndex */) - { - if (Unit* caster = GetCaster()) - if (caster->IsVehicle()) - caster->GetVehicleKit()->RemoveAllPassengers(); - } - - void Register() OVERRIDE - { - OnEffectHitTarget += SpellEffectFn(spell_jokkum_eject_all_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const OVERRIDE - { - return new spell_jokkum_eject_all_SpellScript(); - } -}; - enum CloseRift { SPELL_DESPAWN_RIFT = 61665 @@ -877,6 +851,5 @@ void AddSC_storm_peaks() new npc_king_jokkum_vehicle(); new spell_jokkum_scriptcast(); new spell_veranus_summon(); - new spell_jokkum_eject_all(); new spell_close_rift(); } diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index 8f5ae0f65ff..0f542b3aca7 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -453,7 +453,11 @@ public: struct npc_alchemist_finklesteinAI : public ScriptedAI { - npc_alchemist_finklesteinAI(Creature* creature) : ScriptedAI(creature) { } + npc_alchemist_finklesteinAI(Creature* creature) : ScriptedAI(creature) + { + _playerGUID = 0; + _getingredienttry = 0; + } void Reset() OVERRIDE { |
