/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 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 Affero 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 . */ #include "AreaDefines.h" #include "CreatureScript.h" #include "PassiveAI.h" #include "Player.h" #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" #include "ScriptedFollowerAI.h" #include "ScriptedGossip.h" #include "SpellAuras.h" #include "SpellInfo.h" #include "SpellScript.h" #include "SpellScriptLoader.h" enum eDrakeHunt { SPELL_DRAKE_HATCHLING_SUBDUED = 46691, SPELL_SUBDUED = 46675 }; class spell_q11919_q11940_drake_hunt_aura : public AuraScript { PrepareAuraScript(spell_q11919_q11940_drake_hunt_aura); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_SUBDUED, SPELL_DRAKE_HATCHLING_SUBDUED }); } bool Load() override { return GetOwner()->IsCreature(); } void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE || !GetCaster()) return; Creature* owner = GetOwner()->ToCreature(); owner->RemoveAllAurasExceptType(SPELL_AURA_DUMMY); owner->CombatStop(true); owner->GetThreatMgr().ClearAllThreat(); owner->GetMotionMaster()->Clear(false); owner->GetMotionMaster()->MoveFollow(GetCaster(), 4.0f, M_PI, MOTION_SLOT_ACTIVE); owner->CastSpell(owner, SPELL_SUBDUED, true); GetCaster()->CastSpell(GetCaster(), SPELL_DRAKE_HATCHLING_SUBDUED, true); owner->SetFaction(FACTION_FRIENDLY); owner->SetImmuneToAll(true); owner->DespawnOrUnsummon(180s); } void Register() override { AfterEffectRemove += AuraEffectRemoveFn(spell_q11919_q11940_drake_hunt_aura::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; /*###### ## npc_sinkhole_kill_credit ######*/ enum Sinkhole { GO_EXPLOSIVES_CART = 188160, NPC_SCOURGED_BURROWER = 26250, QUEST_PLUG_THE_SINKHOLES = 11897, SPELL_SET_CART = 46797, SPELL_EXPLODE_CART = 46799, SPELL_SUMMON_CART = 46798, SPELL_SUMMON_WORM = 46800, }; class npc_sinkhole_kill_credit : public CreatureScript { public: npc_sinkhole_kill_credit() : CreatureScript("npc_sinkhole_kill_credit") { } struct npc_sinkhole_kill_creditAI : public NullCreatureAI { npc_sinkhole_kill_creditAI(Creature* creature) : NullCreatureAI(creature) { } uint32 phaseTimer; uint8 phase; ObjectGuid casterGuid; void Reset() override { phaseTimer = 30000; phase = 0; casterGuid.Clear(); } void SpellHit(Unit* caster, SpellInfo const* spell) override { if (phase || spell->Id != SPELL_SET_CART) return; Player* player = caster->ToPlayer(); if (player && player->GetQuestStatus(QUEST_PLUG_THE_SINKHOLES) == QUEST_STATUS_INCOMPLETE) { phase = 1; phaseTimer = 0; casterGuid = caster->GetGUID(); } } void UpdateAI(uint32 diff) override { if (!phase) return; if (phaseTimer <= diff) { switch (phase) { case 1: DoCast(me, SPELL_EXPLODE_CART, true); DoCast(me, SPELL_SUMMON_CART, true); if (GameObject* cart = me->FindNearestGameObject(GO_EXPLOSIVES_CART, 3.0f)) cart->SetUInt32Value(GAMEOBJECT_FACTION, 14); phaseTimer = 3000; phase = 2; break; case 2: if (GameObject* cart = me->FindNearestGameObject(GO_EXPLOSIVES_CART, 3.0f)) cart->UseDoorOrButton(); DoCast(me, SPELL_EXPLODE_CART, true); phaseTimer = 3000; phase = 3; break; case 3: DoCast(me, SPELL_EXPLODE_CART, true); phaseTimer = 2000; phase = 5; // @fixme: phase 4 is missing... break; case 5: DoCast(me, SPELL_SUMMON_WORM, true); if (Unit* worm = me->FindNearestCreature(NPC_SCOURGED_BURROWER, 3.0f)) { worm->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); worm->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); } phaseTimer = 1000; phase = 6; break; case 6: DoCast(me, SPELL_EXPLODE_CART, true); if (Unit* worm = me->FindNearestCreature(NPC_SCOURGED_BURROWER, 3.0f)) { Unit::Kill(me, worm); worm->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE); } phaseTimer = 2000; phase = 7; break; case 7: DoCast(me, SPELL_EXPLODE_CART, true); if (Player* caster = ObjectAccessor::GetPlayer(*me, casterGuid)) caster->KilledMonster(me->GetCreatureTemplate(), me->GetGUID()); phaseTimer = 5000; phase = 8; break; default: CreatureAI::EnterEvadeMode(); break; } } else phaseTimer -= diff; } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_sinkhole_kill_creditAI(creature); } }; /*###### ## npc_khunok_the_behemoth ######*/ enum Khunok { NPC_ORPHANED_MAMMOTH_CALF = 25861, SPELL_MAMMOTH_CALF_ESCORT_CREDIT = 46231 }; class npc_khunok_the_behemoth : public CreatureScript { public: npc_khunok_the_behemoth() : CreatureScript("npc_khunok_the_behemoth") { } struct npc_khunok_the_behemothAI : public ScriptedAI { npc_khunok_the_behemothAI(Creature* creature) : ScriptedAI(creature) { } void MoveInLineOfSight(Unit* who) override { ScriptedAI::MoveInLineOfSight(who); if (!who->IsCreature()) return; if (who->GetEntry() == NPC_ORPHANED_MAMMOTH_CALF && me->IsWithinDistInMap(who, 10.0f)) { if (Unit* owner = who->GetOwner()) { if (owner->IsPlayer()) { owner->CastSpell(owner, SPELL_MAMMOTH_CALF_ESCORT_CREDIT, true); who->ToCreature()->DespawnOrUnsummon(); } } } } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_khunok_the_behemothAI(creature); } }; /*###### ## npc_iruk ######*/ enum Iruk { GOSSIP_MENU_ID_NPC_IRUK = 9280, GOSSIP_OPTION_SEARCH_CORPSE = 0, NPC_TEXT_THIS_YOUNG_TUSKARR = 12585, QUEST_SPIRITS_WATCH_OVER_US = 11961, SPELL_CREATE_TOTEM_OF_ISSLIRUK = 46816 }; class npc_iruk : public CreatureScript { public: npc_iruk() : CreatureScript("npc_iruk") { } bool OnGossipHello(Player* player, Creature* creature) override { if (player->GetQuestStatus(QUEST_SPIRITS_WATCH_OVER_US) == QUEST_STATUS_INCOMPLETE) AddGossipItemFor(player, GOSSIP_MENU_ID_NPC_IRUK, GOSSIP_OPTION_SEARCH_CORPSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); SendGossipMenuFor(player, NPC_TEXT_THIS_YOUNG_TUSKARR, creature->GetGUID()); return true; } bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override { ClearGossipMenuFor(player); if (action == GOSSIP_ACTION_INFO_DEF + 1) { player->CastSpell(player, SPELL_CREATE_TOTEM_OF_ISSLIRUK, true); CloseGossipMenuFor(player); } return true; } }; /*###### ## npc_nerubar_victim ######*/ enum Nerubar { NPC_WARSONG_PEON = 25270, QUEST_TAKEN_BY_THE_SCOURGE = 11611, SPELL_FREED_WARSONG_MAGE = 45526, SPELL_FREED_WARSONG_SHAMAN = 45527, SPELL_FREED_WARSONG_WARRIOR = 45514, SPELL_FREED_WARSONG_PEON = 45532 }; const uint32 nerubarVictims[3] = { SPELL_FREED_WARSONG_MAGE, SPELL_FREED_WARSONG_SHAMAN, SPELL_FREED_WARSONG_WARRIOR }; class npc_nerubar_victim : public CreatureScript { public: npc_nerubar_victim() : CreatureScript("npc_nerubar_victim") { } struct npc_nerubar_victimAI : public NullCreatureAI { npc_nerubar_victimAI(Creature* creature) : NullCreatureAI(creature) { } void JustDied(Unit* killer) override { if (!killer || !killer->IsPlayer()) { return; } Player* player = killer->ToPlayer(); if (player->GetQuestStatus(QUEST_TAKEN_BY_THE_SCOURGE) == QUEST_STATUS_INCOMPLETE) { uint8 uiRand = urand(0, 99); if (uiRand < 40) { player->CastSpell(me, SPELL_FREED_WARSONG_PEON, true); player->KilledMonsterCredit(NPC_WARSONG_PEON); } else if (uiRand < 80) { player->CastSpell(me, nerubarVictims[urand(0, 2)], true); } } } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_nerubar_victimAI(creature); } }; /*###### ## npc_lurgglbr ######*/ enum Lurgglbr { QUEST_ESCAPE_WINTERFIN_CAVERNS = 11570, GO_CAGE = 187369, SAY_START_1 = 0, SAY_START_2 = 1, SAY_END_1 = 2, SAY_END_2 = 3 }; class npc_lurgglbr : public CreatureScript { public: npc_lurgglbr() : CreatureScript("npc_lurgglbr") { } struct npc_lurgglbrAI : public npc_escortAI { npc_lurgglbrAI(Creature* creature) : npc_escortAI(creature) { } uint32 IntroTimer; uint32 IntroPhase; void Reset() override { if (!HasEscortState(STATE_ESCORT_ESCORTING)) { IntroTimer = 0; IntroPhase = 0; } } void WaypointReached(uint32 waypointId) override { switch (waypointId) { case 0: IntroPhase = 1; IntroTimer = 2000; break; case 41: IntroPhase = 4; IntroTimer = 2000; break; } } void UpdateAI(uint32 diff) override { if (IntroPhase) { if (IntroTimer <= diff) { switch (IntroPhase) { case 1: if (Player* player = GetPlayerForEscort()) Talk(SAY_START_1, player); IntroPhase = 2; IntroTimer = 7500; break; case 2: Talk(SAY_START_2); IntroPhase = 3; IntroTimer = 7500; break; case 3: me->SetReactState(REACT_AGGRESSIVE); IntroPhase = 0; IntroTimer = 0; break; case 4: Talk(SAY_END_1); IntroPhase = 5; IntroTimer = 8000; break; case 5: if (Player* player = GetPlayerForEscort()) Talk(SAY_END_2, player); IntroPhase = 6; IntroTimer = 2500; break; case 6: if (Player* player = GetPlayerForEscort()) player->GroupEventHappens(QUEST_ESCAPE_WINTERFIN_CAVERNS, me); IntroPhase = 7; IntroTimer = 2500; break; case 7: me->DespawnOrUnsummon(); IntroPhase = 0; IntroTimer = 0; break; } } else IntroTimer -= diff; } npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_lurgglbrAI(creature); } bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override { if (quest->GetQuestId() == QUEST_ESCAPE_WINTERFIN_CAVERNS) { if (GameObject* go = creature->FindNearestGameObject(GO_CAGE, 5.0f)) go->UseDoorOrButton(); if (npc_escortAI* pEscortAI = CAST_AI(npc_lurgglbr::npc_lurgglbrAI, creature->AI())) { creature->SetWalk(true); pEscortAI->Start(true, player->GetGUID()); } creature->SetFaction(player->GetTeamId() == TEAM_ALLIANCE ? FACTION_ESCORTEE_A_PASSIVE : FACTION_ESCORTEE_H_PASSIVE); return true; } return false; } }; /*###### ## Quest 11881: Load'er Up ######*/ // NPC 25969: Jenny enum Jenny { EVENT_JENNY_START_FOLLOW = 1, EVENT_JENNY_MOVE_TO_FEZZIX = 2, EVENT_JENNY_DESPAWN = 3, SPELL_CRATES_CARRIED = 46340, SPELL_DROP_CRATE = 46342, SPELL_GIVE_JENNY_CREDIT = 46358, NPC_FEZZIX_GEARTWIST = 25849 }; struct npc_jenny : public FollowerAI { npc_jenny(Creature* creature) : FollowerAI(creature) { Initialize(); } void Initialize() { me->SetReactState(REACT_PASSIVE); me->CastSpell(me, SPELL_CRATES_CARRIED); // can't update follow here, call later _events.ScheduleEvent(EVENT_JENNY_START_FOLLOW, 1s); } void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override { if (me->HasAura(SPELL_CRATES_CARRIED)) me->CastSpell(me, SPELL_DROP_CRATE); else me->DespawnOrUnsummon(); } void UpdateFollowerAI(uint32 diff) override { _events.Update(diff); if (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_JENNY_START_FOLLOW: // This NPC only moves at its fixed speed_run rate in the db // and does not inherit the speed of the target if (TempSummon* summon = me->ToTempSummon()) if (Unit* summonerUnit = summon->GetSummonerUnit()) if (Player* summoner = summonerUnit->ToPlayer()) StartFollow(summoner, 0, nullptr, true, false); break; case EVENT_JENNY_MOVE_TO_FEZZIX: me->SetWalk(true); me->GetMotionMaster()->MovePoint(0, _fezzix); _events.ScheduleEvent(EVENT_JENNY_DESPAWN, 7s); break; case EVENT_JENNY_DESPAWN: me->DespawnOrUnsummon(); break; } } } void MoveInLineOfSight(Unit* who) override { if (who->GetEntry() == NPC_FEZZIX_GEARTWIST && me->IsWithinDistInMap(who, 15.0f)) { if (TempSummon* s = me->ToTempSummon()) if (Unit* u = s->GetSummonerUnit()) if (Player* p = u->ToPlayer()) me->CastSpell(p, SPELL_GIVE_JENNY_CREDIT); SetFollowComplete(true); _fezzix = who->GetPosition(); _events.ScheduleEvent(EVENT_JENNY_MOVE_TO_FEZZIX, 1s); } } private: EventMap _events; Position _fezzix; }; /*###### ## Quest 11590: Abduction ######*/ // NPC 25316: Beryl Sorcerer enum BerylSorcerer { EVENT_FROSTBOLT = 1, EVENT_ARCANE_CHAINS = 2, NPC_LIBRARIAN_DONATHAN = 25262, NPC_CAPTURED_BERLY_SORCERER = 25474, SPELL_FROSTBOLT = 9672, SPELL_ARCANE_CHAINS = 45611, SPELL_ARCANE_CHAINS_CHARACTER_FORCE_CAST = 45625, SPELL_ARCANE_CHAINS_SUMMON_CHAINED_MAGE_HUNTER = 45626, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF = 45631, SPELL_ARCANE_CHAINS_CHANNEL_II = 45735 }; class npc_beryl_sorcerer : public CreatureScript { public: npc_beryl_sorcerer() : CreatureScript("npc_beryl_sorcerer") { } struct npc_beryl_sorcererAI : public CreatureAI { npc_beryl_sorcererAI(Creature* creature) : CreatureAI(creature) { Initialize(); } void Initialize() { _playerGUID.Clear(); _chainsCast = false; } void Reset() override { me->SetReactState(REACT_AGGRESSIVE); Initialize(); } void JustEngagedWith(Unit* who) override { if (me->IsValidAttackTarget(who)) { AttackStart(who); } _events.ScheduleEvent(EVENT_FROSTBOLT, 3s, 4s); } void SpellHit(Unit* unit, SpellInfo const* spell) override { if (spell->Id == SPELL_ARCANE_CHAINS && !_chainsCast) { if (Player* player = unit->ToPlayer()) { _playerGUID = player->GetGUID(); _chainsCast = true; _events.ScheduleEvent(EVENT_ARCANE_CHAINS, 4s); } } } void UpdateAI(uint32 diff) override { if (!UpdateVictim()) { return; } _events.Update(diff); if (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_FROSTBOLT: DoCastVictim(SPELL_FROSTBOLT); _events.ScheduleEvent(EVENT_FROSTBOLT, 3s, 4s); break; case EVENT_ARCANE_CHAINS: if (me->HasAura(SPELL_ARCANE_CHAINS)) { if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { me->CastSpell(player, SPELL_ARCANE_CHAINS_CHARACTER_FORCE_CAST, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS & ~TRIGGERED_IGNORE_CAST_ITEM)); player->KilledMonsterCredit(NPC_CAPTURED_BERLY_SORCERER); me->DisappearAndDie(); } } break; } } DoMeleeAttackIfReady(); } private: EventMap _events; ObjectGuid _playerGUID; bool _chainsCast; }; CreatureAI* GetAI(Creature* creature) const override { return new npc_beryl_sorcererAI(creature); } }; // NPC 25474: Captured Beryl Sorcerer enum CapturedBerylSorcerer { EVENT_ADD_ARCANE_CHAINS = 1, EVENT_FOLLOW_PLAYER = 2 }; class npc_captured_beryl_sorcerer : public CreatureScript { public: npc_captured_beryl_sorcerer() : CreatureScript("npc_captured_beryl_sorcerer") {} struct npc_captured_beryl_sorcererAI : public FollowerAI { npc_captured_beryl_sorcererAI(Creature* creature) : FollowerAI(creature) { Initialize(); } void Initialize() { me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); _events.ScheduleEvent(EVENT_ADD_ARCANE_CHAINS, 0ms); } void Reset() override { Initialize(); } void UpdateAI(uint32 diff) override { _events.Update(diff); if (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_ADD_ARCANE_CHAINS: if (TempSummon* tempSummon = me->ToTempSummon()) { if (Unit* summoner = tempSummon->GetSummonerUnit()) { summoner->CastSpell(summoner, SPELL_ARCANE_CHAINS_CHANNEL_II, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS & ~TRIGGERED_IGNORE_CAST_ITEM & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST & ~TRIGGERED_IGNORE_GCD)); _events.ScheduleEvent(EVENT_FOLLOW_PLAYER, 1s); } } break; case EVENT_FOLLOW_PLAYER: if (TempSummon* tempSummon = me->ToTempSummon()) { if (Player* summoner = tempSummon->GetSummonerUnit()->ToPlayer()) { StartFollow(summoner); } } break; } } } void MoveInLineOfSight(Unit* who) override { FollowerAI::MoveInLineOfSight(who); if (who->GetEntry() == NPC_LIBRARIAN_DONATHAN && me->IsWithinDistInMap(who, INTERACTION_DISTANCE)) { SetFollowComplete(); me->DespawnOrUnsummon(); } } private: EventMap _events; }; CreatureAI* GetAI(Creature* creature) const override { return new npc_captured_beryl_sorcererAI(creature); } }; // Spell 45625: - Arcane Chains: Character Force Cast class spell_arcane_chains_character_force_cast : public SpellScript { PrepareSpellScript(spell_arcane_chains_character_force_cast); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_ARCANE_CHAINS_SUMMON_CHAINED_MAGE_HUNTER, 45626 }); } void HandleScriptEffect(SpellEffIndex /* effIndex */) { GetHitUnit()->CastSpell(GetCaster(), SPELL_ARCANE_CHAINS_SUMMON_CHAINED_MAGE_HUNTER, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SET_FACING & ~TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS & ~TRIGGERED_IGNORE_CAST_ITEM & ~TRIGGERED_IGNORE_GCD)); // Player cast back 45626 on npc } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_arcane_chains_character_force_cast::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; /*###### ## npc_imprisoned_beryl_sorcerer ######*/ enum ImprisionedBerylSorcerer { SPELL_NEURAL_NEEDLE = 45634, NPC_IMPRISONED_BERYL_SORCERER = 25478, SAY_IMPRISIONED_BERYL_1 = 0, SAY_IMPRISIONED_BERYL_2 = 1, SAY_IMPRISIONED_BERYL_3 = 2, SAY_IMPRISIONED_BERYL_4 = 3, SAY_IMPRISIONED_BERYL_5 = 4, SAY_IMPRISIONED_BERYL_6 = 5, SAY_IMPRISIONED_BERYL_7 = 6 }; class npc_imprisoned_beryl_sorcerer : public CreatureScript { public: npc_imprisoned_beryl_sorcerer() : CreatureScript("npc_imprisoned_beryl_sorcerer") { } struct npc_imprisoned_beryl_sorcererAI : public ScriptedAI { npc_imprisoned_beryl_sorcererAI(Creature* creature) : ScriptedAI(creature) { } uint32 rebuff; void Reset() override { if (me->GetReactState() != REACT_PASSIVE) me->SetReactState(REACT_PASSIVE); rebuff = 0; // xinef: correct visuals me->UpdatePosition(me->GetPositionX(), me->GetPositionY(), 150.517f, me->GetOrientation(), true); me->SetStandState(UNIT_STAND_STATE_SIT_MEDIUM_CHAIR); } void UpdateAI(uint32 diff) override { UpdateVictim(); if (rebuff <= diff) { if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF)) { DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF); } rebuff = 180000; } else rebuff -= diff; DoMeleeAttackIfReady(); } void JustEngagedWith(Unit* /*who*/) override { } void SpellHit(Unit* unit, SpellInfo const* spell) override { if (spell->Id == SPELL_NEURAL_NEEDLE && unit->IsPlayer()) { if (Player* player = unit->ToPlayer()) { GotStinged(player->GetGUID()); } } } void GotStinged(ObjectGuid casterGUID) { if (Player* caster = ObjectAccessor::GetPlayer(*me, casterGUID)) { uint32 step = caster->GetAuraCount(SPELL_NEURAL_NEEDLE) + 1; switch (step) { case 1: Talk(SAY_IMPRISIONED_BERYL_1); break; case 2: Talk(SAY_IMPRISIONED_BERYL_2, caster); break; case 3: Talk(SAY_IMPRISIONED_BERYL_3); break; case 4: Talk(SAY_IMPRISIONED_BERYL_4); break; case 5: Talk(SAY_IMPRISIONED_BERYL_5); break; case 6: Talk(SAY_IMPRISIONED_BERYL_6, caster); break; case 7: Talk(SAY_IMPRISIONED_BERYL_7); caster->KilledMonsterCredit(NPC_IMPRISONED_BERYL_SORCERER); break; } } } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_imprisoned_beryl_sorcererAI(creature); } }; /*###### ## npc_mootoo_the_younger ######*/ enum MootooTheYounger { SAY_1 = 0, SAY_2 = 1, SAY_3 = 2, SAY_4 = 3, SAY_5 = 4, NPC_MOOTOO_THE_YOUNGER = 25504, QUEST_ESCAPING_THE_MIST = 11664 }; class npc_mootoo_the_younger : public CreatureScript { public: npc_mootoo_the_younger() : CreatureScript("npc_mootoo_the_younger") { } bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override { if (quest->GetQuestId() == QUEST_ESCAPING_THE_MIST) { creature->SetFaction(player->GetTeamId() == TEAM_ALLIANCE ? FACTION_ESCORTEE_A_PASSIVE : FACTION_ESCORTEE_H_PASSIVE); creature->SetStandState(UNIT_STAND_STATE_STAND); creature->AI()->Talk(SAY_1, player); creature->SetWalk(true); CAST_AI(npc_escortAI, (creature->AI()))->Start(true, player->GetGUID()); } return true; } struct npc_mootoo_the_youngerAI : public npc_escortAI { npc_mootoo_the_youngerAI(Creature* creature) : npc_escortAI(creature) { } void Reset() override { SetDespawnAtFar(false); } void JustDied(Unit* /*killer*/) override { if (Player* player = GetPlayerForEscort()) player->FailQuest(QUEST_ESCAPING_THE_MIST); } void WaypointReached(uint32 waypointId) override { Player* player = GetPlayerForEscort(); if (!player) return; switch (waypointId) { case 10: me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); Talk(SAY_2); break; case 12: Talk(SAY_3); me->HandleEmoteCommand(EMOTE_ONESHOT_LOOT); break; case 16: Talk(SAY_4); me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); break; case 20: me->SetPhaseMask(1, true); Talk(SAY_5); me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); player->GroupEventHappens(QUEST_ESCAPING_THE_MIST, me); me->SetWalk(false); break; } } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_mootoo_the_youngerAI(creature); } }; /*###### ## npc_bonker_togglevolt ######*/ enum BonkerTogglevolt { NPC_BONKER_TOGGLEVOLT = 25589, QUEST_GET_ME_OUTA_HERE = 11673, SAY_BONKER_1 = 0, SAY_BONKER_2 = 1 }; class npc_bonker_togglevolt : public CreatureScript { public: npc_bonker_togglevolt() : CreatureScript("npc_bonker_togglevolt") { } bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override { if (quest->GetQuestId() == QUEST_GET_ME_OUTA_HERE) { creature->SetStandState(UNIT_STAND_STATE_STAND); creature->AI()->Talk(SAY_BONKER_2, player); CAST_AI(npc_escortAI, (creature->AI()))->Start(true, player->GetGUID()); } return true; } struct npc_bonker_togglevoltAI : public npc_escortAI { npc_bonker_togglevoltAI(Creature* creature) : npc_escortAI(creature) { } uint32 Bonker_agro; void Reset() override { Bonker_agro = 0; SetDespawnAtFar(false); } void JustDied(Unit* /*killer*/) override { if (Player* player = GetPlayerForEscort()) player->FailQuest(QUEST_GET_ME_OUTA_HERE); } void UpdateEscortAI(uint32 /*diff*/) override { if (GetAttack() && UpdateVictim()) { if (Bonker_agro == 0) { Talk(SAY_BONKER_1); Bonker_agro++; } DoMeleeAttackIfReady(); } else Bonker_agro = 0; } void WaypointReached(uint32 waypointId) override { Player* player = GetPlayerForEscort(); if (!player) return; switch (waypointId) { case 29: player->GroupEventHappens(QUEST_GET_ME_OUTA_HERE, me); break; } } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_bonker_togglevoltAI(creature); } }; /*###### ## Help Those That Cannot Help Themselves, Quest 11876 ######*/ enum Valiancekeepcannons { GO_VALIANCE_KEEP_CANNON_1 = 187560, GO_VALIANCE_KEEP_CANNON_2 = 188692 }; class npc_valiance_keep_cannoneer : public CreatureScript { public: npc_valiance_keep_cannoneer() : CreatureScript("npc_valiance_keep_cannoneer") { } struct npc_valiance_keep_cannoneerAI : public ScriptedAI { npc_valiance_keep_cannoneerAI(Creature* creature) : ScriptedAI(creature) { } uint32 uiTimer; void Reset() override { uiTimer = urand(13000, 18000); } void UpdateAI(uint32 diff) override { if (uiTimer <= diff) { me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); GameObject* pCannon = me->FindNearestGameObject(GO_VALIANCE_KEEP_CANNON_1, 10); if (!pCannon) pCannon = me->FindNearestGameObject(GO_VALIANCE_KEEP_CANNON_2, 10); if (pCannon) pCannon->Use(me); uiTimer = urand(13000, 18000); } else uiTimer -= diff; if (!UpdateVictim()) return; } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_valiance_keep_cannoneerAI(creature); } }; /******************************************************* * npc_warmage_coldarra *******************************************************/ enum Spells { SPELL_TRANSITUS_SHIELD_BEAM = 48310 }; enum NPCs { NPC_TRANSITUS_SHIELD_DUMMY = 27306, NPC_WARMAGE_HOLLISTER = 27906, NPC_WARMAGE_CALANDRA = 27173, NPC_WARMAGE_WATKINS = 27904 }; class npc_warmage_coldarra : public CreatureScript { public: npc_warmage_coldarra() : CreatureScript("npc_warmage_coldarra") { } struct npc_warmage_coldarraAI : public ScriptedAI { npc_warmage_coldarraAI(Creature* creature) : ScriptedAI(creature) { me->SetCombatMovement(false); } uint32 m_uiTimer; //Timer until recast void Reset() override { m_uiTimer = 0; } void JustEngagedWith(Unit* /*who*/) override { } void AttackStart(Unit* /*who*/) override { } void UpdateAI(uint32 uiDiff) override { if (m_uiTimer <= uiDiff) { std::list orbList; GetCreatureListWithEntryInGrid(orbList, me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f); switch (me->GetEntry()) { case NPC_WARMAGE_HOLLISTER: { if (!orbList.empty()) { for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) { if (Creature* pOrb = *itr) if (pOrb->GetPositionY() > 6680) DoCast(pOrb, SPELL_TRANSITUS_SHIELD_BEAM); } } m_uiTimer = urand(90000, 120000); } break; case NPC_WARMAGE_CALANDRA: { if (!orbList.empty()) { for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) { if (Creature* pOrb = *itr) if ((pOrb->GetPositionY() < 6680) && (pOrb->GetPositionY() > 6630)) DoCast(pOrb, SPELL_TRANSITUS_SHIELD_BEAM); } } m_uiTimer = urand(90000, 120000); } break; case NPC_WARMAGE_WATKINS: { if (!orbList.empty()) { for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) { if (Creature* pOrb = *itr) if (pOrb->GetPositionY() < 6630) DoCast(pOrb, SPELL_TRANSITUS_SHIELD_BEAM); } } m_uiTimer = urand(90000, 120000); } break; } } else m_uiTimer -= uiDiff; ScriptedAI::UpdateAI(uiDiff); if (!UpdateVictim()) return; } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_warmage_coldarraAI(creature); } }; /*###### ## Quest 11794: The hunt is on ######*/ // NPCs 25827: Tom Hegger, 25248: Salty John Thorpe, 25828: Guard Mitchells enum HiddenCultist { SPELL_SHROUD_OF_THE_DEATH_CULTIST = 46077, SPELL_RIGHTEOUS_VISION = 46078, NPC_TOM_HEGGER = 25827, NPC_SALTY_JOHN_THORPE = 25248, NPC_GUARD_MITCHELLS = 25828, SAY_HIDDEN_CULTIST_1 = 0, SAY_HIDDEN_CULTIST_2 = 1, SAY_HIDDEN_CULTIST_3 = 2, SAY_HIDDEN_CULTIST_4 = 3, EVENT_CULTIST_SCRIPT_1 = 1, EVENT_CULTIST_SCRIPT_2 = 2, EVENT_CULTIST_SCRIPT_3 = 3 }; class npc_hidden_cultist : public CreatureScript { public: npc_hidden_cultist() : CreatureScript("npc_hidden_cultist") { } struct npc_hidden_cultistAI : public ScriptedAI { npc_hidden_cultistAI(Creature* creature) : ScriptedAI(creature) { Initialize(); _emoteState = creature->GetUInt32Value(UNIT_NPC_EMOTESTATE); _npcFlags = creature->GetNpcFlags(); } void Initialize() { _playerGUID.Clear(); } void Reset() override { if (_emoteState) { me->SetUInt32Value(UNIT_NPC_EMOTESTATE, _emoteState); } if (_npcFlags) { me->ReplaceAllNpcFlags(_npcFlags); } Initialize(); DoCast(SPELL_SHROUD_OF_THE_DEATH_CULTIST); me->RestoreFaction(); } void PreScript() { me->StopMoving(); me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { me->SetFacingToObject(player); } _events.ScheduleEvent(EVENT_CULTIST_SCRIPT_1, 3s); } void AttackPlayer() { me->SetFaction(FACTION_MONSTER); if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { AttackStart(player); } } void UpdateAI(uint32 diff) override { _events.Update(diff); while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_CULTIST_SCRIPT_1: { switch (me->GetEntry()) { case NPC_SALTY_JOHN_THORPE: Talk(SAY_HIDDEN_CULTIST_1); _events.ScheduleEvent(EVENT_CULTIST_SCRIPT_2, 5s); break; case NPC_GUARD_MITCHELLS: Talk(SAY_HIDDEN_CULTIST_2); _events.ScheduleEvent(EVENT_CULTIST_SCRIPT_2, 5s); break; case NPC_TOM_HEGGER: if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { Talk(SAY_HIDDEN_CULTIST_3, player); } _events.ScheduleEvent(EVENT_CULTIST_SCRIPT_2, 5s); break; } break; } case EVENT_CULTIST_SCRIPT_2: { switch (me->GetEntry()) { case NPC_SALTY_JOHN_THORPE: Talk(SAY_HIDDEN_CULTIST_4); if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { me->SetFacingToObject(player); } _events.ScheduleEvent(EVENT_CULTIST_SCRIPT_3, 3s); break; case NPC_GUARD_MITCHELLS: case NPC_TOM_HEGGER: AttackPlayer(); break; } break; } case EVENT_CULTIST_SCRIPT_3: { if (me->GetEntry() == NPC_SALTY_JOHN_THORPE) { AttackPlayer(); } break; } default: break; } } if (!UpdateVictim()) { return; } DoMeleeAttackIfReady(); } void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override { if (gossipListId == 0) { CloseGossipMenuFor(player); _playerGUID = player->GetGUID(); PreScript(); } } private: EventMap _events; uint32 _emoteState; NPCFlags _npcFlags; ObjectGuid _playerGUID; }; CreatureAI* GetAI(Creature* creature) const override { return new npc_hidden_cultistAI(creature); } }; enum BloodsporeRuination { NPC_BLOODMAGE_LAURITH = 25381, SAY_BLOODMAGE_LAURITH = 0, EVENT_TALK = 1, EVENT_RESET_ORIENTATION }; class spell_q11719_bloodspore_ruination_45997 : public SpellScript { PrepareSpellScript(spell_q11719_bloodspore_ruination_45997); void HandleEffect(SpellEffIndex /*effIndex*/) { if (Unit* caster = GetCaster()) if (Creature* laurith = caster->FindNearestCreature(NPC_BLOODMAGE_LAURITH, 100.0f)) laurith->AI()->SetGUID(caster->GetGUID()); } void Register() override { OnEffectHit += SpellEffectFn(spell_q11719_bloodspore_ruination_45997::HandleEffect, EFFECT_1, SPELL_EFFECT_SEND_EVENT); } }; class npc_bloodmage_laurith : public CreatureScript { public: npc_bloodmage_laurith() : CreatureScript("npc_bloodmage_laurith") { } struct npc_bloodmage_laurithAI : public ScriptedAI { npc_bloodmage_laurithAI(Creature* creature) : ScriptedAI(creature) { } void Reset() override { _events.Reset(); _playerGUID.Clear(); } void SetGUID(ObjectGuid const& guid, int32 /*action*/) override { if (_playerGUID) return; _playerGUID = guid; if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) me->SetFacingToObject(player); _events.ScheduleEvent(EVENT_TALK, 1s); } void UpdateAI(uint32 diff) override { if (UpdateVictim()) { DoMeleeAttackIfReady(); return; } _events.Update(diff); if (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_TALK: if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) Talk(SAY_BLOODMAGE_LAURITH, player); _playerGUID.Clear(); _events.ScheduleEvent(EVENT_RESET_ORIENTATION, 5s); break; case EVENT_RESET_ORIENTATION: me->SetFacingTo(me->GetHomePosition().GetOrientation()); break; } } } private: EventMap _events; ObjectGuid _playerGUID; }; CreatureAI* GetAI(Creature* creature) const override { return new npc_bloodmage_laurithAI(creature); } }; /*###### ## Quest 12019: Last Rites ######*/ // NPC 26170: Thassarian enum Thassarian { EVENT_THASSARIAN_SCRIPT_1 = 1, EVENT_THASSARIAN_SCRIPT_2 = 2, EVENT_THASSARIAN_SCRIPT_3 = 3, EVENT_THASSARIAN_SCRIPT_4 = 4, EVENT_THASSARIAN_SCRIPT_5 = 5, EVENT_THASSARIAN_SCRIPT_6 = 6, EVENT_THASSARIAN_SCRIPT_7 = 7, EVENT_THASSARIAN_SCRIPT_8 = 8, EVENT_THASSARIAN_SCRIPT_9 = 9, EVENT_THASSARIAN_SCRIPT_10 = 10, EVENT_THASSARIAN_SCRIPT_11 = 11, EVENT_THASSARIAN_SCRIPT_12 = 12, EVENT_THASSARIAN_SCRIPT_13 = 13, EVENT_THASSARIAN_SCRIPT_14 = 14, EVENT_THASSARIAN_SCRIPT_15 = 15, EVENT_THASSARIAN_SCRIPT_16 = 16, EVENT_THASSARIAN_SCRIPT_17 = 17, EVENT_THASSARIAN_SCRIPT_18 = 18, EVENT_THASSARIAN_SCRIPT_19 = 19, EVENT_THASSARIAN_SCRIPT_20 = 20, EVENT_THASSARIAN_SCRIPT_21 = 21, EVENT_THASSARIAN_SCRIPT_22 = 22, EVENT_THASSARIAN_SCRIPT_23 = 23, EVENT_THASSARIAN_SCRIPT_24 = 24, EVENT_THASSARIAN_SCRIPT_25 = 25, EVENT_THASSARIAN_SCRIPT_26 = 26, EVENT_THASSARIAN_SCRIPT_27 = 27, EVENT_THASSARIAN_SCRIPT_28 = 28, EVENT_THASSARIAN_SCRIPT_29 = 29, EVENT_THASSARIAN_CAST = 30, NPC_IMAGE_LICH_KING = 26203, NPC_COUNSELOR_TALBOT = 25301, NPC_PRINCE_VALANAR = 28189, NPC_GENERAL_ARLOS = 25250, NPC_LERYSSA = 25251, NPC_TANATHAL = 26173, SPELL_THASSARIAN_FLAY = 46685, SPELL_TRANSFORM_VALANAR = 46753, SPELL_BLOOD_PRESENCE = 50995, SAY_THASSARIAN_1 = 0, SAY_THASSARIAN_2 = 1, SAY_THASSARIAN_3 = 2, SAY_THASSARIAN_4 = 3, SAY_THASSARIAN_5 = 4, SAY_THASSARIAN_6 = 5, SAY_THASSARIAN_7 = 6, SAY_TALBOT_1 = 0, SAY_TALBOT_2 = 1, SAY_TALBOT_3 = 2, SAY_TALBOT_4 = 3, SAY_LICH_1 = 0, SAY_LICH_2 = 1, SAY_LICH_3 = 2, SAY_ARLOS_1 = 0, SAY_ARLOS_2 = 1, SAY_LERYSSA_1 = 0, SAY_LERYSSA_2 = 1, SAY_LERYSSA_3 = 2, SAY_LERYSSA_4 = 3, PATH_THASSARIAN = 1013030, PATH_ARTHAS = 1013031, PATH_TALBOT = 1013032, PATH_ARLOS = 1013033, PATH_LERYSSA = 1013034 }; class npc_thassarian : public CreatureScript { public: npc_thassarian() : CreatureScript("npc_thassarian") {} struct npc_thassarianAI : public ScriptedAI { npc_thassarianAI(Creature* creature) : ScriptedAI(creature){} void Reset() override { me->SetImmuneToAll(true); _events.ScheduleEvent(EVENT_THASSARIAN_CAST, 1s); } void UpdateAI(uint32 diff) override { _events.Update(diff); if (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_THASSARIAN_CAST: { if (Unit* tanathal = me->FindNearestCreature(NPC_TANATHAL, 10.0f)) { me->CastSpell(tanathal, SPELL_THASSARIAN_FLAY); } } } } } private: EventMap _events; }; CreatureAI* GetAI(Creature* creature) const override { return new npc_thassarianAI(creature); } }; class npc_thassarian2 : public CreatureScript { public: npc_thassarian2() : CreatureScript("npc_thassarian2") {} struct npc_thassarian2AI : public ScriptedAI { npc_thassarian2AI(Creature* creature) : ScriptedAI(creature) { Initialize(); } void Initialize() { _arthasGUID.Clear(); _talbotGUID.Clear(); _leryssaGUID.Clear(); _arlosGUID.Clear(); } void Reset() override { me->SetFaction(FACTION_VALIANCE_EXPEDITION_7); me->SetStandState(UNIT_STAND_STATE_STAND); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); me->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); Initialize(); } void SetData(uint32 /*type*/, uint32 data) override { switch (data) { case NPC_LERYSSA: { if (Creature* arlos = ObjectAccessor::GetCreature(*me, _arlosGUID)) { arlos->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); } if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); leryssa->SetOrientation(4.537856f); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_8, 1s); break; } case NPC_COUNSELOR_TALBOT: { _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_18, 0ms); } break; default: break; } } void MovementInform(uint32 type, uint32 param) override { if (type == WAYPOINT_MOTION_TYPE && param == 2) { me->SetWalk(false); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_1, 2s); } } void UpdateAI(uint32 diff) override { _events.Update(diff); if (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_THASSARIAN_SCRIPT_1: // Summon Arthas and Talbot if (Creature* arthas = me->SummonCreature(NPC_IMAGE_LICH_KING, 3729.4614f, 3520.386f, 473.4048f, 1.361f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) { _arthasGUID = arthas->GetGUID(); arthas->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); arthas->SetReactState(REACT_PASSIVE); arthas->SetWalk(true); } if (Creature* talbot = me->SummonCreature(NPC_COUNSELOR_TALBOT, 3748.7627f, 3614.0374f, 473.4048f, 4.5553f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) { _talbotGUID = talbot->GetGUID(); talbot->SetWalk(true); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_2, 1s); break; case EVENT_THASSARIAN_SCRIPT_2: // Arthas load path if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) { arthas->GetMotionMaster()->MovePath(PATH_ARTHAS, false); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_3, 1s); break; case EVENT_THASSARIAN_SCRIPT_3: // Talbot load path if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->GetMotionMaster()->MovePath(PATH_TALBOT, false); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_4, 20s); break; case EVENT_THASSARIAN_SCRIPT_4: // Talbot transform and knell if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->CastSpell(talbot, SPELL_TRANSFORM_VALANAR); talbot->UpdateEntry(NPC_PRINCE_VALANAR); talbot->SetFullHealth(); talbot->SetFaction(FACTION_UNDEAD_SCOURGE); talbot->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); talbot->SetReactState(REACT_PASSIVE); talbot->SetStandState(UNIT_STAND_STATE_KNEEL); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_5, 7s); break; case EVENT_THASSARIAN_SCRIPT_5: // Talbot say text 1 if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->AI()->Talk(SAY_TALBOT_1); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_6, 9s); break; case EVENT_THASSARIAN_SCRIPT_6: // Summon General Arlos and Leryssa if (Creature* arlos = me->SummonCreature(NPC_GENERAL_ARLOS, 3746.2825f, 3616.3699f, 473.4048f, 4.5029f, TEMPSUMMON_CORPSE_TIMED_DESPAWN)) { _arlosGUID = arlos->GetGUID(); arlos->SetWalk(true); arlos->SetImmuneToAll(true); arlos->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); arlos->GetMotionMaster()->MovePath(PATH_ARLOS, false); } if (Creature* leryssa = me->SummonCreature(NPC_LERYSSA, 3751.0986f, 3614.9219f, 473.4048f, 4.5029f, TEMPSUMMON_CORPSE_TIMED_DESPAWN)) { _leryssaGUID = leryssa->GetGUID(); leryssa->SetWalk(true); leryssa->SetImmuneToAll(true); leryssa->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); leryssa->GetMotionMaster()->MovePath(PATH_LERYSSA, false); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_7, 7s); break; case EVENT_THASSARIAN_SCRIPT_7: // Talbot say text 2 if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->AI()->Talk(SAY_TALBOT_2); } break; case EVENT_THASSARIAN_SCRIPT_8: // Thassarian say text 1 and move to location Talk(SAY_THASSARIAN_1); me->SetWalk(false); me->GetMotionMaster()->MovePoint(0, 3722.527f, 3567.2583f, 477.44086f); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_9, 7s); break; case EVENT_THASSARIAN_SCRIPT_9: // Thassarian say text 2 Talk(SAY_THASSARIAN_2); me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_10, 6s); break; case EVENT_THASSARIAN_SCRIPT_10: // Arthas turn to Thassarian and Talbot stand if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) { arthas->SetFacingToObject(me); } if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->SetStandState(UNIT_STAND_STATE_STAND); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_11, 4s); break; case EVENT_THASSARIAN_SCRIPT_11: // Arthas say text 2 if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) { arthas->AI()->Talk(SAY_LICH_2); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_12, 18s); break; case EVENT_THASSARIAN_SCRIPT_12: // Thassarian say text 3 Talk(SAY_THASSARIAN_3); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_13, 10s); break; case EVENT_THASSARIAN_SCRIPT_13: // Talbot say text 3 if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->AI()->Talk(SAY_TALBOT_3); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_14, 5s); break; case EVENT_THASSARIAN_SCRIPT_14: // Arthas turn to Talbot say text 3 if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) { if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { arthas->SetFacingToObject(talbot); } arthas->AI()->Talk(SAY_LICH_3); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_15, 5s); break; case EVENT_THASSARIAN_SCRIPT_15: // Arthas turn to me and emote if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) { arthas->SetFacingToObject(me); arthas->HandleEmoteCommand(EMOTE_ONESHOT_POINT); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_16, 5s); break; case EVENT_THASSARIAN_SCRIPT_16: // Arthas despawn if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) { arthas->RemoveFromWorld(); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_17, 3s); break; case EVENT_THASSARIAN_SCRIPT_17: // Talbot say text 4 and attack me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->AI()->Talk(SAY_TALBOT_4); talbot->SetFaction(FACTION_UNDEAD_SCOURGE_9); talbot->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); talbot->SetReactState(REACT_AGGRESSIVE); talbot->Attack(me, false); } break; case EVENT_THASSARIAN_SCRIPT_18: // Arlos say text 1 me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H); if (Creature* arlos = ObjectAccessor::GetCreature(*me, _arlosGUID)) { arlos->AI()->Talk(SAY_ARLOS_1); arlos->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); arlos->SetStandState(UNIT_STAND_STATE_KNEEL); } if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_19, 3s); break; case EVENT_THASSARIAN_SCRIPT_19: // Leryssa set facing to me me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); if (Creature* leryssa = me->FindNearestCreature(NPC_LERYSSA, 50.0f, true)) { _leryssaGUID = leryssa->GetGUID(); leryssa->SetFacingToObject(me); me->SetFacingToObject(leryssa); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_20, 3s); break; case EVENT_THASSARIAN_SCRIPT_20: // Arlos say text 2 and die. Leryssa say text 1 if (Creature* arlos = me->FindNearestCreature(NPC_GENERAL_ARLOS, 50.0f, true)) { _arlosGUID = arlos->GetGUID(); arlos->AI()->Talk(SAY_ARLOS_2); arlos->SetStandState(UNIT_STAND_STATE_DEAD); } if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->AI()->Talk(SAY_LERYSSA_1); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_21, 5s); break; case EVENT_THASSARIAN_SCRIPT_21: // Thassarian say text 4 me->SetStandState(UNIT_STAND_STATE_KNEEL); Talk(SAY_THASSARIAN_4); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_22, 3s); break; case EVENT_THASSARIAN_SCRIPT_22: // Leryssa run to Thassarian if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->SetWalk(false); leryssa->GetMotionMaster()->MovePoint(0, 3726.751f, 3568.1633f, 477.44086f, FORCED_MOVEMENT_RUN); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_23, 2s); break; case EVENT_THASSARIAN_SCRIPT_23: // Leryssa say text 2 if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->AI()->Talk(SAY_LERYSSA_2); leryssa->SetStandState(UNIT_STAND_STATE_SIT); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_24, 5s); break; case EVENT_THASSARIAN_SCRIPT_24: // Thassarian say text 5 Talk(SAY_THASSARIAN_5); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_25, 10s); break; case EVENT_THASSARIAN_SCRIPT_25: // Leryssa say text 3 if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->AI()->Talk(SAY_LERYSSA_3); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_26, 12s); break; case EVENT_THASSARIAN_SCRIPT_26: // Thassarian say text 6 Talk(SAY_THASSARIAN_6); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_27, 11s); break; case EVENT_THASSARIAN_SCRIPT_27: // Leryssa say text 4 if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->AI()->Talk(SAY_LERYSSA_4); } _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_28, 12s); break; case EVENT_THASSARIAN_SCRIPT_28: // Thassarian say text 7 Talk(SAY_THASSARIAN_7); _events.ScheduleEvent(EVENT_THASSARIAN_SCRIPT_29, 35s); break; case EVENT_THASSARIAN_SCRIPT_29: Cleanup(); me->DespawnOrUnsummon(30s, 120s); break; default: break; } } if (!UpdateVictim()) { return; } DoMeleeAttackIfReady(); } void JustDied(Unit* /*killer*/) override { Cleanup(); me->DespawnOrUnsummon(1s, 120s); } void Cleanup() { if (Creature* talbot = ObjectAccessor::GetCreature(*me, _talbotGUID)) { talbot->RemoveFromWorld(); } if (Creature* leryssa = ObjectAccessor::GetCreature(*me, _leryssaGUID)) { leryssa->RemoveFromWorld(); } if (Creature* arlos = ObjectAccessor::GetCreature(*me, _arlosGUID)) { arlos->RemoveFromWorld(); } if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID)) { arthas->RemoveFromWorld(); } } void sGossipHello(Player* /*player*/) override { if (!me->HasAura(SPELL_BLOOD_PRESENCE)) { DoCastSelf(SPELL_BLOOD_PRESENCE); } } void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override { if (action == 0) { _playerGUID = player->GetGUID(); CloseGossipMenuFor(player); me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); me->GetMotionMaster()->MovePath(PATH_THASSARIAN, false); } } private: EventMap _events; ObjectGuid _playerGUID; ObjectGuid _arthasGUID; ObjectGuid _talbotGUID; ObjectGuid _leryssaGUID; ObjectGuid _arlosGUID; }; CreatureAI* GetAI(Creature* creature) const override { return new npc_thassarian2AI(creature); } }; // NPC 25251: Leryssa class npc_leryssa : public CreatureScript { public: npc_leryssa() : CreatureScript("npc_leryssa") {} struct npc_leryssaAI : public ScriptedAI { npc_leryssaAI(Creature* creature) : ScriptedAI(creature) {} void MovementInform(uint32 type, uint32 param) override { if (type == WAYPOINT_MOTION_TYPE && param == 2) { if (me->IsSummon()) { if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit()) { summoner->ToCreature()->AI()->SetData(1, NPC_LERYSSA); } } } } }; CreatureAI* GetAI(Creature* creature) const override { return new npc_leryssaAI(creature); } }; // NPC 25301: Counselor Talbot enum CounselorTalbot { SPELL_DEFLECTION = 51009, SPELL_SOUL_BLAST = 50992, SPELL_VAMPIRIC_BOLT = 51016, EVENT_DEFLECTION = 1, EVENT_SOUL_BLAST = 2, EVENT_VAMPIRIC_BOLT = 3 }; class npc_counselor_talbot : public CreatureScript { public: npc_counselor_talbot() : CreatureScript("npc_counselor_talbot") {} struct npc_counselor_talbotAI : public ScriptedAI { npc_counselor_talbotAI(Creature* creature) : ScriptedAI(creature) {} void Reset() override {} void JustEngagedWith(Unit* /*who*/) override { _events.ScheduleEvent(EVENT_DEFLECTION, 10s, 20s); _events.ScheduleEvent(EVENT_SOUL_BLAST, 4s, 6s); _events.ScheduleEvent(EVENT_VAMPIRIC_BOLT, 0ms); } void UpdateAI(uint32 diff) override { if (!UpdateVictim()) { return; } if (me->GetAreaId() == AREA_NAXXANAR) { _events.Update(diff); if (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_DEFLECTION: DoCastSelf(SPELL_DEFLECTION); _events.ScheduleEvent(EVENT_DEFLECTION, 10s, 20s); break; case EVENT_SOUL_BLAST: DoCastVictim(SPELL_SOUL_BLAST); _events.ScheduleEvent(EVENT_SOUL_BLAST, 4s, 6s); break; case EVENT_VAMPIRIC_BOLT: DoCastVictim(SPELL_VAMPIRIC_BOLT); _events.ScheduleEvent(EVENT_VAMPIRIC_BOLT, 3s, 4s); break; default: break; } } } DoMeleeAttackIfReady(); } void JustDied(Unit* /*killer*/) override { if (me->IsSummon()) { if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit()) { summoner->ToCreature()->AI()->SetData(1, NPC_COUNSELOR_TALBOT); } } } private: EventMap _events; }; CreatureAI* GetAI(Creature* creature) const override { return new npc_counselor_talbotAI(creature); } }; // 45612 - Necropolis Beam class spell_necropolis_beam: public SpellScript { PrepareSpellScript(spell_necropolis_beam); void SetDest(SpellDestination& dest) { Unit* caster = GetCaster(); float floorZ = caster->GetMapHeight(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); if (floorZ > INVALID_HEIGHT) dest._position.m_positionZ = floorZ; } void Register() override { OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_necropolis_beam::SetDest, EFFECT_0, TARGET_DEST_CASTER); } }; enum SoulDeflectionSpells { SPELL_SOUL_DEFLECTION_DAMAGE = 51011 }; class spell_soul_deflection : public AuraScript { PrepareAuraScript(spell_soul_deflection); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_SOUL_DEFLECTION_DAMAGE }); } void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) { if (!eventInfo.GetDamageInfo() || !eventInfo.GetDamageInfo()->GetDamage() || !GetTarget()) return; GetCaster()->CastCustomSpell(SPELL_SOUL_DEFLECTION_DAMAGE, SPELLVALUE_BASE_POINT0, eventInfo.GetDamageInfo()->GetDamage(), GetTarget(), true); } void Register() override { OnEffectProc += AuraEffectProcFn(spell_soul_deflection::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } }; void AddSC_borean_tundra() { RegisterSpellScript(spell_q11919_q11940_drake_hunt_aura); new npc_thassarian(); new npc_thassarian2(); new npc_leryssa(); new npc_counselor_talbot(); new npc_sinkhole_kill_credit(); new npc_khunok_the_behemoth(); new npc_iruk(); new npc_nerubar_victim(); new npc_lurgglbr(); new npc_beryl_sorcerer(); new npc_captured_beryl_sorcerer(); RegisterSpellScript(spell_arcane_chains_character_force_cast); new npc_imprisoned_beryl_sorcerer(); new npc_mootoo_the_younger(); new npc_bonker_togglevolt(); new npc_valiance_keep_cannoneer(); new npc_warmage_coldarra(); new npc_hidden_cultist(); RegisterSpellScript(spell_q11719_bloodspore_ruination_45997); new npc_bloodmage_laurith(); RegisterCreatureAI(npc_jenny); RegisterSpellScript(spell_necropolis_beam); RegisterSpellScript(spell_soul_deflection); }