diff options
| author | Rat <none@none> | 2010-01-19 11:36:05 +0100 |
|---|---|---|
| committer | Rat <none@none> | 2010-01-19 11:36:05 +0100 |
| commit | 0cc053ea4d42ce405a915857f75ee00f0f65666b (patch) | |
| tree | 7c25955ee5db618deee963f515ba061fbb1e1e8c /src/scripts/outland/shadowmoon_valley.cpp | |
| parent | f5dea61b66a616110cfc82ff640ec448b1efa702 (diff) | |
*Integrate Script system to Core
-added ScriptMgr for loading scripts
-removed bindings
-moved script system to src/game
-moved scripts to src/scripts
-VC project files updated
-cmakes updated (not 100% done yet)
NOTE to Devs:
-file locations changed
-precompiled renamed to ScriptedPch
-ecsort_ai renamed to ScriptedEscortAI
-follower_ai renamed to ScriptedFollowerAI
-guard_ai renamed to ScriptedGuardAI
-simple_ai renamed to ScriptedSimpleAI
-sc_creature renamed to ScriptedCreature
-sc_gossip renamed to ScriptedGossip
-sc_instance renamed to ScriptedInstance
*use the new headers in scripts, thank you
NOTE to ALL:
cmake not fully tested, please report any errors with it
could make creashes, incompability
USE AT YOUR OWN RISK before further tests!!
--HG--
branch : trunk
Diffstat (limited to 'src/scripts/outland/shadowmoon_valley.cpp')
| -rw-r--r-- | src/scripts/outland/shadowmoon_valley.cpp | 1827 |
1 files changed, 1827 insertions, 0 deletions
diff --git a/src/scripts/outland/shadowmoon_valley.cpp b/src/scripts/outland/shadowmoon_valley.cpp new file mode 100644 index 00000000000..0942f897cc6 --- /dev/null +++ b/src/scripts/outland/shadowmoon_valley.cpp @@ -0,0 +1,1827 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>.sourceforge.net/> + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shadowmoon_Valley +SD%Complete: 100 +SDComment: Quest support: 10519, 10583, 10601, 10814, 10804, 10854, 10458, 10481, 10480, 11082, 10781, 10451. Vendor Drake Dealer Hurlunk. +SDCategory: Shadowmoon Valley +EndScriptData */ + +/* ContentData +mob_mature_netherwing_drake +mob_enslaved_netherwing_drake +npc_drake_dealer_hurlunk +npcs_flanis_swiftwing_and_kagrosh +npc_murkblood_overseer +npc_neltharaku +npc_karynaku +npc_oronok_tornheart +npc_overlord_morghor +npc_earthmender_wilda +mob_torloth_the_magnificent +mob_illidari_spawn +npc_lord_illidan_stormrage +go_crystal_prison +npc_enraged_spirit +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*##### +# mob_mature_netherwing_drake +#####*/ + +enum eMatureNetherwing +{ + SAY_JUST_EATEN = -1000222, + + SPELL_PLACE_CARCASS = 38439, + SPELL_JUST_EATEN = 38502, + SPELL_NETHER_BREATH = 38467, + POINT_ID = 1, + + GO_CARCASS = 185155, + + QUEST_KINDNESS = 10804, + NPC_EVENT_PINGER = 22131 +}; + +struct TRINITY_DLL_DECL mob_mature_netherwing_drakeAI : public ScriptedAI +{ + mob_mature_netherwing_drakeAI(Creature* c) : ScriptedAI(c) { } + + uint64 uiPlayerGUID; + + bool bCanEat; + bool bIsEating; + + uint32 EatTimer; + uint32 CastTimer; + + void Reset() + { + uiPlayerGUID = 0; + + bCanEat = false; + bIsEating = false; + + EatTimer = 5000; + CastTimer = 5000; + } + + void SpellHit(Unit* pCaster, SpellEntry const* pSpell) + { + if (bCanEat || bIsEating) + return; + + if (pCaster->GetTypeId() == TYPEID_PLAYER && pSpell->Id == SPELL_PLACE_CARCASS && !m_creature->HasAura(SPELL_JUST_EATEN)) + { + uiPlayerGUID = pCaster->GetGUID(); + bCanEat = true; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == POINT_ID) + { + bIsEating = true; + EatTimer = 7000; + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); + } + } + + void UpdateAI(const uint32 diff) + { + if (bCanEat || bIsEating) + { + if (EatTimer <= diff) + { + if (bCanEat && !bIsEating) + { + if (Unit* pUnit = Unit::GetUnit(*m_creature, uiPlayerGUID)) + { + if (GameObject* pGo = pUnit->FindNearestGameObject(GO_CARCASS, 10)) + { + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + m_creature->GetMotionMaster()->MovementExpired(); + + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->StopMoving(); + + m_creature->GetMotionMaster()->MovePoint(POINT_ID, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ()); + } + } + bCanEat = false; + } + else if (bIsEating) + { + DoCast(m_creature, SPELL_JUST_EATEN); + DoScriptText(SAY_JUST_EATEN, m_creature); + + if (Player* pPlr = Unit::GetPlayer(uiPlayerGUID)) + { + pPlr->KilledMonsterCredit(NPC_EVENT_PINGER, m_creature->GetGUID()); + + if (GameObject* pGo = pPlr->FindNearestGameObject(GO_CARCASS, 10)) + pGo->Delete(); + } + + Reset(); + m_creature->GetMotionMaster()->Clear(); + } + } + else + EatTimer -= diff; + + return; + } + + if (!UpdateVictim()) + return; + + if (CastTimer <= diff) + { + DoCast(m_creature->getVictim(), SPELL_NETHER_BREATH); + CastTimer = 5000; + } else CastTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_mature_netherwing_drake(Creature* pCreature) +{ + return new mob_mature_netherwing_drakeAI(pCreature); +} + +/*### +# mob_enslaved_netherwing_drake +####*/ + +#define FACTION_DEFAULT 62 +#define FACTION_FRIENDLY 1840 // Not sure if this is correct, it was taken off of Mordenai. + +#define SPELL_HIT_FORCE_OF_NELTHARAKU 38762 +#define SPELL_FORCE_OF_NELTHARAKU 38775 + +#define CREATURE_DRAGONMAW_SUBJUGATOR 21718 +#define CREATURE_ESCAPE_DUMMY 22317 + +struct TRINITY_DLL_DECL mob_enslaved_netherwing_drakeAI : public ScriptedAI +{ + mob_enslaved_netherwing_drakeAI(Creature* c) : ScriptedAI(c) + { + PlayerGUID = 0; + Tapped = false; + Reset(); + } + + uint64 PlayerGUID; + uint32 FlyTimer; + bool Tapped; + + void Reset() + { + if (!Tapped) + m_creature->setFaction(FACTION_DEFAULT); + + FlyTimer = 10000; + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + m_creature->SetVisibility(VISIBILITY_ON); + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if (!caster) + return; + + if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_HIT_FORCE_OF_NELTHARAKU && !Tapped) + { + Tapped = true; + PlayerGUID = caster->GetGUID(); + + m_creature->setFaction(FACTION_FRIENDLY); + DoCast(caster, SPELL_FORCE_OF_NELTHARAKU, true); + + Unit* Dragonmaw = me->FindNearestCreature(CREATURE_DRAGONMAW_SUBJUGATOR, 50); + + if (Dragonmaw) + { + m_creature->AddThreat(Dragonmaw, 100000.0f); + AttackStart(Dragonmaw); + } + + HostilReference* ref = m_creature->getThreatManager().getOnlineContainer().getReferenceByTarget(caster); + if (ref) + ref->removeReference(); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + { + if (PlayerGUID) + { + Unit* plr = Unit::GetUnit((*m_creature), PlayerGUID); + if (plr) + DoCast(plr, SPELL_FORCE_OF_NELTHARAKU, true); + + PlayerGUID = 0; + } + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (Tapped) + if (FlyTimer <= diff) + { + Tapped = false; + if (PlayerGUID) + { + Player* plr = Unit::GetPlayer(PlayerGUID); + if (plr && plr->GetQuestStatus(10854) == QUEST_STATUS_INCOMPLETE) + { + DoCast(plr, SPELL_FORCE_OF_NELTHARAKU, true); + /* + float x,y,z; + m_creature->GetPosition(x,y,z); + + float dx,dy,dz; + m_creature->GetRandomPoint(x, y, z, 20, dx, dy, dz); + dz += 20; // so it's in the air, not ground*/ + + Position pos; + if(Unit* EscapeDummy = me->FindNearestCreature(CREATURE_ESCAPE_DUMMY, 30)) + EscapeDummy->GetPosition(&pos); + else + { + m_creature->GetRandomNearPosition(pos, 20); + pos.m_positionZ += 25; + } + + m_creature->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + m_creature->GetMotionMaster()->MovePoint(1, pos); + } + } + } else FlyTimer -= diff; + return; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_enslaved_netherwing_drake(Creature* pCreature) +{ + return new mob_enslaved_netherwing_drakeAI(pCreature); +} + +/*##### +# mob_dragonmaw_peon +#####*/ + +struct TRINITY_DLL_DECL mob_dragonmaw_peonAI : public ScriptedAI +{ + mob_dragonmaw_peonAI(Creature* c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + bool Tapped; + uint32 PoisonTimer; + + void Reset() + { + PlayerGUID = 0; + Tapped = false; + PoisonTimer = 0; + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if (!caster) + return; + + if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == 40468 && !Tapped) + { + PlayerGUID = caster->GetGUID(); + + Tapped = true; + float x, y, z; + caster->GetClosePoint(x, y, z, m_creature->GetObjectSize()); + + m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + m_creature->GetMotionMaster()->MovePoint(1, x, y, z); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id) + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_EAT); + PoisonTimer = 15000; + } + } + + void UpdateAI(const uint32 diff) + { + if (PoisonTimer) + if (PoisonTimer <= diff) + { + if (PlayerGUID) + { + Player* plr = Unit::GetPlayer(PlayerGUID); + if (plr && plr->GetQuestStatus(11020) == QUEST_STATUS_INCOMPLETE) + plr->KilledMonsterCredit(23209, m_creature->GetGUID()); + } + PoisonTimer = 0; + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } else PoisonTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_dragonmaw_peon(Creature* pCreature) +{ + return new mob_dragonmaw_peonAI(pCreature); +} + +/*###### +## npc_drake_dealer_hurlunk +######*/ + +bool GossipHello_npc_drake_dealer_hurlunk(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isVendor() && pPlayer->GetReputationRank(1015) == REP_EXALTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_drake_dealer_hurlunk(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_flanis_swiftwing_and_kagrosh +######*/ + +#define GOSSIP_HSK1 "Take Flanis's Pack" +#define GOSSIP_HSK2 "Take Kagrosh's Pack" + +bool GossipHello_npcs_flanis_swiftwing_and_kagrosh(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(10583) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(30658,1,true)) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HSK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (pPlayer->GetQuestStatus(10601) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(30659,1,true)) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HSK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_flanis_swiftwing_and_kagrosh(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30658, 1, false); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, 30658, 1, true); + pPlayer->PlayerTalkClass->ClearMenus(); + } + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30659, 1, false); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, 30659, 1, true); + pPlayer->PlayerTalkClass->ClearMenus(); + } + } + return true; +} + +/*###### +## npc_murkblood_overseer +######*/ + +#define QUEST_11082 11082 + +#define GOSSIP_HMO "I am here for you, overseer." +#define GOSSIP_SMO1 "How dare you question an overseer of the Dragonmaw!" +#define GOSSIP_SMO2 "Who speaks of me? What are you talking about, broken?" +#define GOSSIP_SMO3 "Continue please." +#define GOSSIP_SMO4 "Who are these bidders?" +#define GOSSIP_SMO5 "Well... yes." + +bool GossipHello_npc_murkblood_overseer(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_11082) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HMO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_murkblood_overseer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + pCreature->CastSpell(pPlayer,41121,false); + pPlayer->AreaExploredOrEventHappens(QUEST_11082); + break; + } + return true; +} + +/*###### +## npc_neltharaku +######*/ + +#define GOSSIP_HN "I am listening, dragon" +#define GOSSIP_SN1 "But you are dragons! How could orcs do this to you?" +#define GOSSIP_SN2 "Your mate?" +#define GOSSIP_SN3 "I have battled many beasts, dragon. I will help you." + +bool GossipHello_npc_neltharaku(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(10814) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(10613, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_neltharaku(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(10614, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(10615, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(10616, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(10814); + break; + } + return true; +} + +/*###### +## npc_oronok +######*/ + +#define GOSSIP_ORONOK1 "I am ready to hear your story, Oronok." +#define GOSSIP_ORONOK2 "How do I find the cipher?" +#define GOSSIP_ORONOK3 "How do you know all of this?" +#define GOSSIP_ORONOK4 "Yet what? What is it, Oronok?" +#define GOSSIP_ORONOK5 "Continue, please." +#define GOSSIP_ORONOK6 "So what of the cipher now? And your boys?" +#define GOSSIP_ORONOK7 "I will find your boys and the cipher, Oronok." + +bool GossipHello_npc_oronok_tornheart(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (pPlayer->GetQuestStatus(10519) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(10312, pCreature->GetGUID()); + }else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_oronok_tornheart(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10313, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(10314, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(10315, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(10316, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(10317, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(10318, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(10519); + break; + } + return true; +} + +/*#### +# npc_karynaku +####*/ + +enum eKarynaku +{ + QUEST_ALLY_OF_NETHER = 10870, + + TAXI_PATH_ID = 649 +}; + +bool QuestAccept_npc_karynaku(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_ALLY_OF_NETHER) + pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID); //pPlayer->ActivateTaxiPathTo(649); + + return true; +} + +/*#### +# npc_overlord_morghor +####*/ + +#define QUEST_LORD_ILLIDAN_STORMRAGE 11108 + +#define C_ILLIDAN 22083 +#define C_YARZILL 23141 + +#define SPELL_ONE 39990 // Red Lightning Bolt +#define SPELL_TWO 41528 // Mark of Stormrage +#define SPELL_THREE 40216 // Dragonaw Faction +#define SPELL_FOUR 42016 // Dragonaw Trasform + +#define OVERLORD_SAY_1 -1000206 +#define OVERLORD_SAY_2 -1000207 +#define OVERLORD_SAY_3 -1000208 //signed for 28315 +#define OVERLORD_SAY_4 -1000209 +#define OVERLORD_SAY_5 -1000210 +#define OVERLORD_SAY_6 -1000211 + +#define OVERLORD_YELL_1 -1000212 +#define OVERLORD_YELL_2 -1000213 + +#define LORD_ILLIDAN_SAY_1 -1000214 +#define LORD_ILLIDAN_SAY_2 -1000215 +#define LORD_ILLIDAN_SAY_3 -1000216 +#define LORD_ILLIDAN_SAY_4 -1000217 +#define LORD_ILLIDAN_SAY_5 -1000218 +#define LORD_ILLIDAN_SAY_6 -1000219 +#define LORD_ILLIDAN_SAY_7 -1000220 + +#define YARZILL_THE_MERC_SAY -1000221 + +struct TRINITY_DLL_DECL npc_overlord_morghorAI : public ScriptedAI +{ + npc_overlord_morghorAI(Creature *c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + uint64 IllidanGUID; + + uint32 ConversationTimer; + uint32 Step; + + bool Event; + + void Reset() + { + PlayerGUID = 0; + IllidanGUID = 0; + + ConversationTimer = 0; + Step = 0; + + Event = false; + } + + void StartEvent() + { + m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + Unit* Illidan = m_creature->SummonCreature(C_ILLIDAN, -5107.83, 602.584, 85.2393, 4.92598, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Illidan) + { + IllidanGUID = Illidan->GetGUID(); + Illidan->SetVisibility(VISIBILITY_OFF); + } + if (PlayerGUID) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer) + DoScriptText(OVERLORD_SAY_1, m_creature, pPlayer); + } + ConversationTimer = 4200; + Step = 0; + Event = true; + } + + uint32 NextStep(uint32 Step) + { + Unit* plr = Unit::GetUnit((*m_creature), PlayerGUID); + + Unit* Illi = Unit::GetUnit((*m_creature), IllidanGUID); + + if (!plr || !Illi) + { + EnterEvadeMode(); + return 0; + } + + switch(Step) + { + case 0: return 0; break; + case 1: m_creature->GetMotionMaster()->MovePoint(0, -5104.41, 595.297, 85.6838); return 9000; break; + case 2: DoScriptText(OVERLORD_YELL_1, m_creature, plr); return 4500; break; + case 3: m_creature->SetInFront(plr); return 3200; break; + case 4: DoScriptText(OVERLORD_SAY_2, m_creature, plr); return 2000; break; + case 5: Illi->SetVisibility(VISIBILITY_ON); + Illi->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); return 350; break; + case 6: + Illi->CastSpell(Illi, SPELL_ONE, true); + Illi->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); + return 2000; break; + case 7: DoScriptText(OVERLORD_YELL_2, m_creature); return 4500; break; + case 8: m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); return 2500; break; + case 9: DoScriptText(OVERLORD_SAY_3, m_creature); return 6500; break; + case 10: DoScriptText(LORD_ILLIDAN_SAY_1, Illi); return 5000; break; + case 11: DoScriptText(OVERLORD_SAY_4, m_creature, plr); return 6000; break; + case 12: DoScriptText(LORD_ILLIDAN_SAY_2, Illi); return 5500; break; + case 13: DoScriptText(LORD_ILLIDAN_SAY_3, Illi); return 4000; break; + case 14: Illi->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); return 1500; break; + case 15: DoScriptText(LORD_ILLIDAN_SAY_4, Illi); return 1500; break; + case 16: + if (plr) + { + Illi->CastSpell(plr, SPELL_TWO, true); + plr->RemoveAurasDueToSpell(SPELL_THREE); + plr->RemoveAurasDueToSpell(SPELL_FOUR); + return 5000; + }else{ + CAST_PLR(plr)->FailQuest(QUEST_LORD_ILLIDAN_STORMRAGE); Step = 30; return 100; + } + break; + case 17: DoScriptText(LORD_ILLIDAN_SAY_5, Illi); return 5000; break; + case 18: DoScriptText(LORD_ILLIDAN_SAY_6, Illi); return 5000; break; + case 19: DoScriptText(LORD_ILLIDAN_SAY_7, Illi); return 5000; break; + case 20: + Illi->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + Illi->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + return 500; break; + case 21: DoScriptText(OVERLORD_SAY_5, m_creature); return 500; break; + case 22: + Illi->SetVisibility(VISIBILITY_OFF); + Illi->setDeathState(JUST_DIED); + return 1000; break; + case 23: m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); return 2000; break; + case 24: m_creature->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); return 5000; break; + case 25: DoScriptText(OVERLORD_SAY_6, m_creature); return 2000; break; + case 26: + if (plr) + CAST_PLR(plr)->GroupEventHappens(QUEST_LORD_ILLIDAN_STORMRAGE, m_creature); + return 6000; break; + case 27: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + Yarzill->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); + return 500; } + break; + case 28: + plr->RemoveAurasDueToSpell(SPELL_TWO); + plr->RemoveAurasDueToSpell(41519); + plr->CastSpell(plr, SPELL_THREE, true); + plr->CastSpell(plr, SPELL_FOUR, true); + return 1000; break; + case 29: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + DoScriptText(YARZILL_THE_MERC_SAY, Yarzill, plr); + return 5000; } + break; + case 30: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + Yarzill->SetUInt64Value(UNIT_FIELD_TARGET, 0); + return 5000; } + break; + case 31: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + Yarzill->CastSpell(plr, 41540, true); + return 1000;} +break; + case 32: m_creature->GetMotionMaster()->MovePoint(0, -5085.77, 577.231, 86.6719); return 5000; break; + case 33: Reset(); return 100; break; + + default : return 0; + } + } + + void UpdateAI(const uint32 diff) + { + if (!ConversationTimer) + return; + + if (ConversationTimer <= diff) + { + if (Event && IllidanGUID && PlayerGUID) + { + ConversationTimer = NextStep(++Step); + } + } else ConversationTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_overlord_morghor(Creature* pCreature) +{ +return new npc_overlord_morghorAI(pCreature); +} + +bool QuestAccept_npc_overlord_morghor(Player* pPlayer, Creature* pCreature, const Quest *_Quest) +{ + if (_Quest->GetQuestId() == QUEST_LORD_ILLIDAN_STORMRAGE) + { + CAST_AI(npc_overlord_morghorAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); + CAST_AI(npc_overlord_morghorAI, pCreature->AI())->StartEvent(); + return true; + } + return false; +} + +/*#### +# npc_earthmender_wilda +####*/ + +enum eEarthmender +{ + SAY_WIL_START = -1000381, + SAY_WIL_AGGRO1 = -1000382, + SAY_WIL_AGGRO2 = -1000383, + SAY_WIL_PROGRESS1 = -1000384, + SAY_WIL_PROGRESS2 = -1000385, + SAY_WIL_FIND_EXIT = -1000386, + SAY_WIL_PROGRESS4 = -1000387, + SAY_WIL_PROGRESS5 = -1000388, + SAY_WIL_JUST_AHEAD = -1000389, + SAY_WIL_END = -1000390, + + SPELL_CHAIN_LIGHTNING = 16006, + SPELL_EARTHBING_TOTEM = 15786, + SPELL_FROST_SHOCK = 12548, + SPELL_HEALING_WAVE = 12491, + + QUEST_ESCAPE_COILSCAR = 10451, + NPC_COILSKAR_ASSASSIN = 21044, + FACTION_EARTHEN = 1726 //guessed +}; + +struct TRINITY_DLL_DECL npc_earthmender_wildaAI : public npc_escortAI +{ + npc_earthmender_wildaAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + uint32 m_uiHealingTimer; + + void Reset() + { + m_uiHealingTimer = 0; + } + + void WaypointReached(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 13: + DoScriptText(SAY_WIL_PROGRESS1, m_creature, pPlayer); + DoSpawnAssassin(); + break; + case 14: + DoSpawnAssassin(); + break; + case 15: + DoScriptText(SAY_WIL_FIND_EXIT, m_creature, pPlayer); + break; + case 19: + DoRandomSay(); + break; + case 20: + DoSpawnAssassin(); + break; + case 26: + DoRandomSay(); + break; + case 27: + DoSpawnAssassin(); + break; + case 33: + DoRandomSay(); + break; + case 34: + DoSpawnAssassin(); + break; + case 37: + DoRandomSay(); + break; + case 38: + DoSpawnAssassin(); + break; + case 39: + DoScriptText(SAY_WIL_JUST_AHEAD, m_creature, pPlayer); + break; + case 43: + DoRandomSay(); + break; + case 44: + DoSpawnAssassin(); + break; + case 50: + DoScriptText(SAY_WIL_END, m_creature, pPlayer); + + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_ESCAPE_COILSCAR, m_creature); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_COILSKAR_ASSASSIN) + pSummoned->AI()->AttackStart(m_creature); + } + + //this is very unclear, random say without no real relevance to script/event + void DoRandomSay() + { + DoScriptText(RAND(SAY_WIL_PROGRESS2,SAY_WIL_PROGRESS4,SAY_WIL_PROGRESS5), m_creature); + } + + void DoSpawnAssassin() + { + //unknown where they actually appear + DoSummon(NPC_COILSKAR_ASSASSIN, me, 15.0f, 5000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT); + } + + void Aggro(Unit* pWho) + { + //don't always use + if (rand()%5) + return; + + //only aggro text if not player + if (pWho->GetTypeId() != TYPEID_PLAYER) + { + //appears to be random + if (urand(0,1)) + DoScriptText(RAND(SAY_WIL_AGGRO1, SAY_WIL_AGGRO2), pWho); + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + //TODO: add more abilities + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() <= 30) + { + if (m_uiHealingTimer <= uiDiff) + { + DoCast(m_creature, SPELL_HEALING_WAVE); + m_uiHealingTimer = 15000; + } + else + m_uiHealingTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_earthmender_wilda(Creature* pCreature) +{ + return new npc_earthmender_wildaAI(pCreature); +} + +bool QuestAccept_npc_earthmender_wilda(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_ESCAPE_COILSCAR) + { + DoScriptText(SAY_WIL_START, pCreature, pPlayer); + pCreature->setFaction(FACTION_EARTHEN); + + if (npc_earthmender_wildaAI* pEscortAI = CAST_AI(npc_earthmender_wildaAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return true; +} + +/*##### +# Quest: Battle of the crimson watch +#####*/ + +/* ContentData +Battle of the crimson watch - creatures, gameobjects and defines +mob_illidari_spawn : Adds that are summoned in the Crimson Watch battle. +mob_torloth_the_magnificent : Final Creature that players have to face before quest is completed +npc_lord_illidan_stormrage : Creature that controls the event. +go_crystal_prison : GameObject that begins the event and hands out quest +EndContentData */ + +#define END_TEXT -1000366 //signed for 10646 + +#define QUEST_BATTLE_OF_THE_CRIMSON_WATCH 10781 +#define EVENT_AREA_RADIUS 65 //65yds +#define EVENT_COOLDOWN 30000 //in ms. appear after event completed or failed (should be = Adds despawn time) + +struct TorlothCinematic +{ + int32 TextId; + uint32 pCreature, Timer; +}; + +// Creature 0 - Torloth, 1 - Illidan +static TorlothCinematic TorlothAnim[]= +{ + {-1000367, 0, 2000}, + {-1000368, 1, 7000}, + {-1000369, 0, 3000}, + {NULL, 0, 2000}, // Torloth stand + {-1000370, 0, 1000}, + {NULL, 0, 3000}, + {NULL, 0, NULL} +}; + +struct Location +{ + float x, y, z, o; +}; + +//Cordinates for Spawns +static Location SpawnLocation[]= +{ + //Cords used for: + {-4615.8556, 1342.2532, 139.9, 1.612},//Illidari Soldier + {-4598.9365, 1377.3182, 139.9, 3.917},//Illidari Soldier + {-4598.4697, 1360.8999, 139.9, 2.427},//Illidari Soldier + {-4589.3599, 1369.1061, 139.9, 3.165},//Illidari Soldier + {-4608.3477, 1386.0076, 139.9, 4.108},//Illidari Soldier + {-4633.1889, 1359.8033, 139.9, 0.949},//Illidari Soldier + {-4623.5791, 1351.4574, 139.9, 0.971},//Illidari Soldier + {-4607.2988, 1351.6099, 139.9, 2.416},//Illidari Soldier + {-4633.7764, 1376.0417, 139.9, 5.608},//Illidari Soldier + {-4600.2461, 1369.1240, 139.9, 3.056},//Illidari Mind Breaker + {-4631.7808, 1367.9459, 139.9, 0.020},//Illidari Mind Breaker + {-4600.2461, 1369.1240, 139.9, 3.056},//Illidari Highlord + {-4631.7808, 1367.9459, 139.9, 0.020},//Illidari Highlord + {-4615.5586, 1353.0031, 139.9, 1.540},//Illidari Highlord + {-4616.4736, 1384.2170, 139.9, 4.971},//Illidari Highlord + {-4627.1240, 1378.8752, 139.9, 2.544} //Torloth The Magnificent +}; + +struct WaveData +{ + uint8 SpawnCount, UsedSpawnPoint; + uint32 CreatureId, SpawnTimer,YellTimer; + int32 WaveTextId; +}; + +static WaveData WavesInfo[]= +{ + {9, 0, 22075, 10000, 7000, -1000371}, //Illidari Soldier + {2, 9, 22074, 10000, 7000, -1000372}, //Illidari Mind Breaker + {4, 11, 19797, 10000, 7000, -1000373}, //Illidari Highlord + {1, 15, 22076, 10000, 7000, -1000374} //Torloth The Magnificent +}; + +struct SpawnSpells +{ + uint32 Timer1, Timer2, SpellId; +}; + +static SpawnSpells SpawnCast[]= +{ + {10000, 15000, 35871}, // Illidari Soldier Cast - Spellbreaker + {10000, 10000, 38985}, // Illidari Mind Breake Cast - Focused Bursts + {35000, 35000, 22884}, // Illidari Mind Breake Cast - Psychic Scream + {20000, 20000, 17194}, // Illidari Mind Breake Cast - Mind Blast + {8000, 15000, 38010}, // Illidari Highlord Cast - Curse of Flames + {12000, 20000, 16102}, // Illidari Highlord Cast - Flamestrike + {10000, 15000, 15284}, // Torloth the Magnificent Cast - Cleave + {18000, 20000, 39082}, // Torloth the Magnificent Cast - Shadowfury + {25000, 28000, 33961} // Torloth the Magnificent Cast - Spell Reflection +}; + +/*###### +# mob_illidari_spawn +######*/ + +struct TRINITY_DLL_DECL mob_illidari_spawnAI : public ScriptedAI +{ + mob_illidari_spawnAI(Creature* c) : ScriptedAI(c) {} + + uint64 LordIllidanGUID; + uint32 SpellTimer1, SpellTimer2, SpellTimer3; + bool Timers; + + void Reset() + { + LordIllidanGUID = 0; + Timers = false; + } + + void EnterCombat(Unit* who) {} + void JustDied(Unit* slayer); + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!Timers) + { + if (m_creature->GetEntry() == 22075)//Illidari Soldier + { + SpellTimer1 = SpawnCast[0].Timer1 + (rand()%4 * 1000); + } + if (m_creature->GetEntry() == 22074)//Illidari Mind Breaker + { + SpellTimer1 = SpawnCast[1].Timer1 + (rand()%10 * 1000); + SpellTimer2 = SpawnCast[2].Timer1 + (rand()%4 * 1000); + SpellTimer3 = SpawnCast[3].Timer1 + (rand()%4 * 1000); + } + if (m_creature->GetEntry() == 19797)// Illidari Highlord + { + SpellTimer1 = SpawnCast[4].Timer1 + (rand()%4 * 1000); + SpellTimer2 = SpawnCast[5].Timer1 + (rand()%4 * 1000); + } + Timers = true; + } + //Illidari Soldier + if (m_creature->GetEntry() == 22075) + { + if (SpellTimer1 <= diff) + { + DoCast(m_creature->getVictim(), SpawnCast[0].SpellId);//Spellbreaker + SpellTimer1 = SpawnCast[0].Timer2 + (rand()%5 * 1000); + } else SpellTimer1 -= diff; + } + //Illidari Mind Breaker + if (m_creature->GetEntry() == 22074) + { + if (SpellTimer1 <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SpawnCast[1].SpellId); //Focused Bursts + SpellTimer1 = SpawnCast[1].Timer2 + (rand()%5 * 1000); + } else SpellTimer1 = 2000; + } + } else SpellTimer1 -= diff; + + if (SpellTimer2 <= diff) + { + DoCast(m_creature->getVictim(), SpawnCast[2].SpellId);//Psychic Scream + SpellTimer2 = SpawnCast[2].Timer2 + (rand()%13 * 1000); + } else SpellTimer2 -= diff; + + if (SpellTimer3 <= diff) + { + DoCast(m_creature->getVictim(), SpawnCast[3].SpellId);//Mind Blast + SpellTimer3 = SpawnCast[3].Timer2 + (rand()%8 * 1000); + } else SpellTimer3 -= diff; + } + //Illidari Highlord + if (m_creature->GetEntry() == 19797) + { + if (SpellTimer1 <= diff) + { + DoCast(m_creature->getVictim(), SpawnCast[4].SpellId);//Curse Of Flames + SpellTimer1 = SpawnCast[4].Timer2 + (rand()%10 * 1000); + } else SpellTimer1 -= diff; + + if (SpellTimer2 <= diff) + { + DoCast(m_creature->getVictim(), SpawnCast[5].SpellId);//Flamestrike + SpellTimer2 = SpawnCast[5].Timer2 + (rand()%7 * 13000); + } else SpellTimer2 -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +# mob_torloth_the_magnificent +#####*/ + +struct TRINITY_DLL_DECL mob_torloth_the_magnificentAI : public ScriptedAI +{ + mob_torloth_the_magnificentAI(Creature* c) : ScriptedAI(c) {} + + uint32 AnimationTimer, SpellTimer1, SpellTimer2, SpellTimer3; + + uint8 AnimationCount; + + uint64 LordIllidanGUID; + uint64 AggroTargetGUID; + + bool Timers; + + void Reset() + { + AnimationTimer = 4000; + AnimationCount = 0; + LordIllidanGUID = 0; + AggroTargetGUID = 0; + Timers = false; + + m_creature->addUnitState(UNIT_STAT_ROOT); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + } + + void EnterCombat(Unit* who){} + + void HandleAnimation() + { + Creature* pCreature = m_creature; + + if (TorlothAnim[AnimationCount].pCreature == 1) + { + pCreature = (Unit::GetCreature(*m_creature, LordIllidanGUID)); + + if (!pCreature) + return; + } + + if (TorlothAnim[AnimationCount].TextId) + DoScriptText(TorlothAnim[AnimationCount].TextId, pCreature); + + AnimationTimer = TorlothAnim[AnimationCount].Timer; + + switch(AnimationCount) + { + case 0: + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,8); + break; + case 3: + m_creature->RemoveFlag(UNIT_FIELD_BYTES_1,8); + break; + case 5: + if (Player* AggroTarget = (Unit::GetPlayer(AggroTargetGUID))) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, AggroTarget->GetGUID()); + m_creature->AddThreat(AggroTarget, 1); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_POINT); + } + break; + case 6: + if (Player* AggroTarget = (Unit::GetPlayer(AggroTargetGUID))) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->clearUnitState(UNIT_STAT_ROOT); + + float x, y, z; + AggroTarget->GetPosition(x,y,z); + m_creature->GetMotionMaster()->MovePoint(0,x,y,z); + } + break; + } + ++AnimationCount; + } + + void UpdateAI(const uint32 diff) + { + if (AnimationTimer) + { + if (AnimationTimer <= diff) + { + HandleAnimation(); + } else AnimationTimer -= diff; + } + + if (AnimationCount < 6) + { + m_creature->CombatStop(); + } else if (!Timers) + { + + SpellTimer1 = SpawnCast[6].Timer1; + SpellTimer2 = SpawnCast[7].Timer1; + SpellTimer3 = SpawnCast[8].Timer1; + Timers = true; + } + + if (Timers) + { + if (SpellTimer1 <= diff) + { + DoCast(m_creature->getVictim(), SpawnCast[6].SpellId);//Cleave + SpellTimer1 = SpawnCast[6].Timer2 + (rand()%10 * 1000); + } else SpellTimer1 -= diff; + + if (SpellTimer2 <= diff) + { + DoCast(m_creature->getVictim(), SpawnCast[7].SpellId);//Shadowfury + SpellTimer2 = SpawnCast[7].Timer2 + (rand()%5 * 1000); + } else SpellTimer2 -= diff; + + if (SpellTimer3 <= diff) + { + DoCast(m_creature, SpawnCast[8].SpellId); + SpellTimer3 = SpawnCast[8].Timer2 + (rand()%7 * 1000);//Spell Reflection + } else SpellTimer3 -= diff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* slayer) + { + if (slayer) + switch(slayer->GetTypeId()) + { + case TYPEID_UNIT: + if (Unit *owner = slayer->GetOwner()) + if (owner->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(owner)->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, m_creature); + break; + + case TYPEID_PLAYER: + CAST_PLR(slayer)->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, m_creature); + break; + } + + if (Creature* LordIllidan = (Unit::GetCreature(*m_creature, LordIllidanGUID))) + { + DoScriptText(END_TEXT, LordIllidan, slayer); + LordIllidan->AI()->EnterEvadeMode(); + } + } +}; + +/*##### +# npc_lord_illidan_stormrage +#####*/ + +struct TRINITY_DLL_DECL npc_lord_illidan_stormrageAI : public ScriptedAI +{ + npc_lord_illidan_stormrageAI(Creature* c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + + uint32 WaveTimer; + uint32 AnnounceTimer; + + int8 LiveCount; + uint8 WaveCount; + + bool EventStarted; + bool Announced; + bool Failed; + + void Reset() + { + PlayerGUID = 0; + + WaveTimer = 10000; + AnnounceTimer = 7000; + LiveCount = 0; + WaveCount = 0; + + EventStarted = false; + Announced = false; + Failed = false; + + m_creature->SetVisibility(VISIBILITY_OFF); + } + + void EnterCombat(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + void AttackStart(Unit* who) {} + + void SummonNextWave() + { + uint8 count = WavesInfo[WaveCount].SpawnCount; + uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint; + srand(time(NULL));//initializing random seed + uint8 FelguardCount = 0; + uint8 DreadlordCount = 0; + + for (uint8 i = 0; i < count; ++i) + { + Creature* Spawn = NULL; + float X = SpawnLocation[locIndex + i].x; + float Y = SpawnLocation[locIndex + i].y; + float Z = SpawnLocation[locIndex + i].z; + float O = SpawnLocation[locIndex + i].o; + Spawn = m_creature->SummonCreature(WavesInfo[WaveCount].CreatureId, X, Y, Z, O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + ++LiveCount; + + if (Spawn) + { + Spawn->LoadCreaturesAddon(); + + if (WaveCount == 0)//1 Wave + { + if (rand()%3 == 1 && FelguardCount<2) + { + Spawn->SetDisplayId(18654); + ++FelguardCount; + } + else if (DreadlordCount < 3) + { + Spawn->SetDisplayId(19991); + ++DreadlordCount; + } + else if (FelguardCount<2) + { + Spawn->SetDisplayId(18654); + ++FelguardCount; + } + } + + if (WaveCount < 3)//1-3 Wave + { + if (PlayerGUID) + { + if (Player* pTarget = Unit::GetPlayer(PlayerGUID)) + { + float x, y, z; + pTarget->GetPosition(x,y,z); + Spawn->GetMotionMaster()->MovePoint(0,x, y, z); + } + } + CAST_AI(mob_illidari_spawnAI, Spawn->AI())->LordIllidanGUID = m_creature->GetGUID(); + } + + if (WavesInfo[WaveCount].CreatureId == 22076) // Torloth + { + CAST_AI(mob_torloth_the_magnificentAI, Spawn->AI())->LordIllidanGUID = m_creature->GetGUID(); + if (PlayerGUID) + CAST_AI(mob_torloth_the_magnificentAI, Spawn->AI())->AggroTargetGUID = PlayerGUID; + } + } + } + ++WaveCount; + WaveTimer = WavesInfo[WaveCount].SpawnTimer; + AnnounceTimer = WavesInfo[WaveCount].YellTimer; + } + + void CheckEventFail() + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!pPlayer) + return; + + if (Group *EventGroup = pPlayer->GetGroup()) + { + Player* GroupMember; + + uint8 GroupMemberCount = 0; + uint8 DeadMemberCount = 0; + uint8 FailedMemberCount = 0; + + const Group::MemberSlotList members = EventGroup->GetMemberSlots(); + + for (Group::member_citerator itr = members.begin(); itr!= members.end(); itr++) + { + GroupMember = (Unit::GetPlayer(itr->guid)); + if (!GroupMember) + continue; + if (!GroupMember->IsWithinDistInMap(m_creature, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) + { + GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); + GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); + ++FailedMemberCount; + } + ++GroupMemberCount; + + if (GroupMember->isDead()) + { + ++DeadMemberCount; + } + } + + if (GroupMemberCount == FailedMemberCount) + { + Failed = true; + } + + if (GroupMemberCount == DeadMemberCount) + { + for (Group::member_citerator itr = members.begin(); itr!= members.end(); itr++) + { + GroupMember = Unit::GetPlayer(itr->guid); + + if (GroupMember && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) + { + GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); + GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); + } + } + Failed = true; + } + } else if (pPlayer->isDead() || !pPlayer->IsWithinDistInMap(m_creature, EVENT_AREA_RADIUS)) + { + pPlayer->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); + Failed = true; + } + } + + void LiveCounter() + { + --LiveCount; + if (!LiveCount) + Announced = false; + } + + void UpdateAI(const uint32 diff) + { + if (!PlayerGUID || !EventStarted) + return; + + if (!LiveCount && WaveCount < 4) + { + if (!Announced && AnnounceTimer <= diff) + { + DoScriptText(WavesInfo[WaveCount].WaveTextId, m_creature); + Announced = true; + } else AnnounceTimer -= diff; + + if (WaveTimer <= diff) + { + SummonNextWave(); + } else WaveTimer -= diff; + } + CheckEventFail(); + + if (Failed) + EnterEvadeMode(); + } +}; + +void mob_illidari_spawnAI::JustDied(Unit *slayer) +{ + m_creature->RemoveCorpse(); + if (Creature* LordIllidan = (Unit::GetCreature(*m_creature, LordIllidanGUID))) + if (LordIllidan) + CAST_AI(npc_lord_illidan_stormrageAI, LordIllidan->AI())->LiveCounter(); +} + +/*##### +# go_crystal_prison +######*/ + +bool GOQuestAccept_GO_crystal_prison(Player* plr, GameObject* go, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_BATTLE_OF_THE_CRIMSON_WATCH) + { + Creature* Illidan = plr->FindNearestCreature(22083, 50); + + if (Illidan && !CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted) + { + CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->PlayerGUID = plr->GetGUID(); + CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->LiveCount = 0; + CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted=true; + } + } + return true; +} + +CreatureAI* GetAI_npc_lord_illidan_stormrage(Creature* c) +{ + return new npc_lord_illidan_stormrageAI(c); +} + +CreatureAI* GetAI_mob_illidari_spawn(Creature* c) +{ + return new mob_illidari_spawnAI(c); +} + +CreatureAI* GetAI_mob_torloth_the_magnificent(Creature* c) +{ + return new mob_torloth_the_magnificentAI(c); +} + +/*#### +# npc_enraged_spirits +####*/ + +/* QUESTS */ +#define QUEST_ENRAGED_SPIRITS_FIRE_EARTH 10458 +#define QUEST_ENRAGED_SPIRITS_AIR 10481 +#define QUEST_ENRAGED_SPIRITS_WATER 10480 + +/* Totem */ +#define ENTRY_TOTEM_OF_SPIRITS 21071 +#define RADIUS_TOTEM_OF_SPIRITS 15 + +/* SPIRITS */ +#define ENTRY_ENRAGED_EARTH_SPIRIT 21050 +#define ENTRY_ENRAGED_FIRE_SPIRIT 21061 +#define ENTRY_ENRAGED_AIR_SPIRIT 21060 +#define ENTRY_ENRAGED_WATER_SPIRIT 21059 + +/* SOULS */ +#define ENTRY_EARTHEN_SOUL 21073 +#define ENTRY_FIERY_SOUL 21097 +#define ENTRY_ENRAGED_AIRY_SOUL 21116 +#define ENTRY_ENRAGED_WATERY_SOUL 21109 // wrong model + +/* SPELL KILLCREDIT - not working!?! - using KilledMonsterCredit */ +#define SPELL_EARTHEN_SOUL_CAPTURED_CREDIT 36108 +#define SPELL_FIERY_SOUL_CAPTURED_CREDIT 36117 +#define SPELL_AIRY_SOUL_CAPTURED_CREDIT 36182 +#define SPELL_WATERY_SOUL_CAPTURED_CREDIT 36171 + +/* KilledMonsterCredit Workaround */ +#define CREDIT_FIRE 21094 +#define CREDIT_WATER 21095 +#define CREDIT_AIR 21096 +#define CREDIT_EARTH 21092 + +/* Captured Spell/Buff */ +#define SPELL_SOUL_CAPTURED 36115 + +/* Factions */ +#define ENRAGED_SOUL_FRIENDLY 35 +#define ENRAGED_SOUL_HOSTILE 14 + +struct TRINITY_DLL_DECL npc_enraged_spiritAI : public ScriptedAI +{ + npc_enraged_spiritAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + + void EnterCombat(Unit *who){} + + void JustDied(Unit* killer) + { + // always spawn spirit on death + // if totem around + // move spirit to totem and cast kill count + uint32 entry = 0; + uint32 credit = 0; + + switch(m_creature->GetEntry()) { + case ENTRY_ENRAGED_FIRE_SPIRIT: + entry = ENTRY_FIERY_SOUL; + //credit = SPELL_FIERY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_FIRE; + break; + case ENTRY_ENRAGED_EARTH_SPIRIT: + entry = ENTRY_EARTHEN_SOUL; + //credit = SPELL_EARTHEN_SOUL_CAPTURED_CREDIT; + credit = CREDIT_EARTH; + break; + case ENTRY_ENRAGED_AIR_SPIRIT: + entry = ENTRY_ENRAGED_AIRY_SOUL; + //credit = SPELL_AIRY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_AIR; + break; + case ENTRY_ENRAGED_WATER_SPIRIT: + entry = ENTRY_ENRAGED_WATERY_SOUL; + //credit = SPELL_WATERY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_WATER; + break; + } + + // Spawn Soul on Kill ALWAYS! + Creature* Summoned = NULL; + Unit* totemOspirits = NULL; + + if (entry != 0) + Summoned = DoSpawnCreature(entry, 0, 0, 1, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000); + + // FIND TOTEM, PROCESS QUEST + if (Summoned) + { + totemOspirits = me->FindNearestCreature(ENTRY_TOTEM_OF_SPIRITS, RADIUS_TOTEM_OF_SPIRITS); + if (totemOspirits) + { + Summoned->setFaction(ENRAGED_SOUL_FRIENDLY); + Summoned->GetMotionMaster()->MovePoint(0,totemOspirits->GetPositionX(), totemOspirits->GetPositionY(), Summoned->GetPositionZ()); + + Unit* Owner = totemOspirits->GetOwner(); + if (Owner && Owner->GetTypeId() == TYPEID_PLAYER) + // DoCast(Owner, credit); -- not working! + CAST_PLR(Owner)->KilledMonsterCredit(credit, Summoned->GetGUID()); + DoCast(totemOspirits, SPELL_SOUL_CAPTURED); + } + } + } +}; + +CreatureAI* GetAI_npc_enraged_spirit(Creature* pCreature) +{ +return new npc_enraged_spiritAI(pCreature); +} + +/*##### +# +######*/ + +void AddSC_shadowmoon_valley() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_mature_netherwing_drake"; + newscript->GetAI = &GetAI_mob_mature_netherwing_drake; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_enslaved_netherwing_drake"; + newscript->GetAI = &GetAI_mob_enslaved_netherwing_drake; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dragonmaw_peon"; + newscript->GetAI = &GetAI_mob_dragonmaw_peon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_drake_dealer_hurlunk"; + newscript->pGossipHello = &GossipHello_npc_drake_dealer_hurlunk; + newscript->pGossipSelect = &GossipSelect_npc_drake_dealer_hurlunk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npcs_flanis_swiftwing_and_kagrosh"; + newscript->pGossipHello = &GossipHello_npcs_flanis_swiftwing_and_kagrosh; + newscript->pGossipSelect = &GossipSelect_npcs_flanis_swiftwing_and_kagrosh; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_murkblood_overseer"; + newscript->pGossipHello = &GossipHello_npc_murkblood_overseer; + newscript->pGossipSelect = &GossipSelect_npc_murkblood_overseer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_neltharaku"; + newscript->pGossipHello = &GossipHello_npc_neltharaku; + newscript->pGossipSelect = &GossipSelect_npc_neltharaku; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_karynaku"; + newscript->pQuestAccept = &QuestAccept_npc_karynaku; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_oronok_tornheart"; + newscript->pGossipHello = &GossipHello_npc_oronok_tornheart; + newscript->pGossipSelect = &GossipSelect_npc_oronok_tornheart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_overlord_morghor"; + newscript->GetAI = &GetAI_npc_overlord_morghor; + newscript->pQuestAccept = &QuestAccept_npc_overlord_morghor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_earthmender_wilda"; + newscript->GetAI = &GetAI_npc_earthmender_wilda; + newscript->pQuestAccept = &QuestAccept_npc_earthmender_wilda; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lord_illidan_stormrage"; + newscript->GetAI = &GetAI_npc_lord_illidan_stormrage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_crystal_prison"; + newscript->pGOQuestAccept = &GOQuestAccept_GO_crystal_prison; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_illidari_spawn"; + newscript->GetAI = &GetAI_mob_illidari_spawn; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_torloth_the_magnificent"; + newscript->GetAI = &GetAI_mob_torloth_the_magnificent; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_enraged_spirit"; + newscript->GetAI = &GetAI_npc_enraged_spirit; + newscript->RegisterSelf(); +} + |
