PageRenderTime 27ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/scripts/eastern_kingdoms/karazhan/karazhan.cpp

https://github.com/vertrigo/scriptdev2
C++ | 433 lines | 330 code | 68 blank | 35 comment | 48 complexity | 4b7e23fbd6f30c85ee59fecff528e253 MD5 | raw file
  1. /* Copyright (C) 2006 - 2012 ScriptDev2 <http://www.scriptdev2.com/>
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License as published by
  4. * the Free Software Foundation; either version 2 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. /* ScriptData
  17. SDName: Karazhan
  18. SD%Complete: 100
  19. SDComment: Support for Barnes (Opera controller) and Berthold (Doorman).
  20. SDCategory: Karazhan
  21. EndScriptData */
  22. /* ContentData
  23. npc_barnes
  24. npc_berthold
  25. EndContentData */
  26. #include "precompiled.h"
  27. #include "karazhan.h"
  28. #include "escort_ai.h"
  29. /*######
  30. # npc_barnesAI
  31. ######*/
  32. #define GOSSIP_READY "I'm not an actor."
  33. #define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!"
  34. #define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?"
  35. #define OZ_GOSSIP1 "I'm not an actor."
  36. #define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!"
  37. #define OZ_GOSSIP2 "Ok, I'll give it a try, then."
  38. #define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?"
  39. #define RAJ_GOSSIP1 "I've never been more ready."
  40. #define OZ_GM_GOSSIP1 "[GM] Change event to EVENT_OZ"
  41. #define OZ_GM_GOSSIP2 "[GM] Change event to EVENT_HOOD"
  42. #define OZ_GM_GOSSIP3 "[GM] Change event to EVENT_RAJ"
  43. struct Dialogue
  44. {
  45. int32 iTextId;
  46. uint32 uiTimer;
  47. };
  48. static Dialogue aOzDialogue[4]=
  49. {
  50. {-1532103, 6000},
  51. {-1532104, 18000},
  52. {-1532105, 9000},
  53. {-1532106, 15000}
  54. };
  55. static Dialogue aHoodDialogue[4]=
  56. {
  57. {-1532107, 6000},
  58. {-1532108, 10000},
  59. {-1532109, 14000},
  60. {-1532110, 15000}
  61. };
  62. static Dialogue aRAJDialogue[4]=
  63. {
  64. {-1532111, 5000},
  65. {-1532112, 7000},
  66. {-1532113, 14000},
  67. {-1532114, 14000}
  68. };
  69. struct Spawn
  70. {
  71. uint32 uiEntry;
  72. float fPosX;
  73. };
  74. // Entries and spawn locations for creatures in Oz event
  75. Spawn aSpawns_OZ[4]=
  76. {
  77. {17535, -10896.0f}, // Dorothee
  78. {17546, -10891.0f}, // Roar
  79. {17547, -10884.0f}, // Tinhead
  80. {17543, -10902.0f}, // Strawman
  81. };
  82. Spawn Spawn_HOOD = {17603, -10892.0f}; // Grandmother
  83. Spawn Spawn_RAJ = {17534, -10900.0f}; // Julianne
  84. enum
  85. {
  86. NPC_SPOTLIGHT = 19525,
  87. SPELL_SPOTLIGHT = 25824,
  88. SPELL_TUXEDO = 32616
  89. };
  90. const float SPAWN_Z = 90.5f;
  91. const float SPAWN_Y = -1758.0f;
  92. const float SPAWN_O = 4.738f;
  93. struct MANGOS_DLL_DECL npc_barnesAI : public npc_escortAI
  94. {
  95. npc_barnesAI(Creature* pCreature) : npc_escortAI(pCreature)
  96. {
  97. m_bRaidWiped = false;
  98. m_uiEventId = 0;
  99. m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
  100. Reset();
  101. }
  102. ScriptedInstance* m_pInstance;
  103. ObjectGuid m_spotlightGuid;
  104. uint32 m_uiTalkCount;
  105. uint32 m_uiTalkTimer;
  106. uint32 m_uiWipeTimer;
  107. uint32 m_uiEventId;
  108. bool m_bPerformanceReady;
  109. bool m_bRaidWiped;
  110. void Reset()
  111. {
  112. m_spotlightGuid.Clear();
  113. m_uiTalkCount = 0;
  114. m_uiTalkTimer = 2000;
  115. m_uiWipeTimer = 5000;
  116. m_bPerformanceReady = false;
  117. if (m_pInstance)
  118. m_uiEventId = m_pInstance->GetData(DATA_OPERA_PERFORMANCE);
  119. }
  120. void StartEvent()
  121. {
  122. if (!m_pInstance)
  123. return;
  124. m_pInstance->SetData(TYPE_OPERA, IN_PROGRESS);
  125. //resets count for this event, in case earlier failed
  126. if (m_uiEventId == EVENT_OZ)
  127. m_pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS);
  128. Start(false, NULL, NULL, true);
  129. }
  130. void WaypointReached(uint32 uiPointId)
  131. {
  132. if (!m_pInstance)
  133. return;
  134. switch(uiPointId)
  135. {
  136. case 0:
  137. m_creature->CastSpell(m_creature, SPELL_TUXEDO, false);
  138. m_pInstance->DoUseDoorOrButton(GO_STAGE_DOOR_LEFT);
  139. break;
  140. case 4:
  141. m_uiTalkCount = 0;
  142. SetEscortPaused(true);
  143. if (Creature* pSpotlight = m_creature->SummonCreature(NPC_SPOTLIGHT,
  144. m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0.0f,
  145. TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
  146. {
  147. pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  148. pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false);
  149. m_spotlightGuid = pSpotlight->GetObjectGuid();
  150. }
  151. break;
  152. case 8:
  153. m_pInstance->DoUseDoorOrButton(GO_STAGE_DOOR_LEFT);
  154. m_bPerformanceReady = true;
  155. break;
  156. case 9:
  157. PrepareEncounter();
  158. m_pInstance->DoUseDoorOrButton(GO_STAGE_CURTAIN);
  159. break;
  160. }
  161. }
  162. void Talk(uint32 uiCount)
  163. {
  164. int32 iTextId = 0;
  165. switch(m_uiEventId)
  166. {
  167. case EVENT_OZ:
  168. if (aOzDialogue[uiCount].iTextId)
  169. iTextId = aOzDialogue[uiCount].iTextId;
  170. if (aOzDialogue[uiCount].uiTimer)
  171. m_uiTalkTimer = aOzDialogue[uiCount].uiTimer;
  172. break;
  173. case EVENT_HOOD:
  174. if (aHoodDialogue[uiCount].iTextId)
  175. iTextId = aHoodDialogue[uiCount].iTextId;
  176. if (aHoodDialogue[uiCount].uiTimer)
  177. m_uiTalkTimer = aHoodDialogue[uiCount].uiTimer;
  178. break;
  179. case EVENT_RAJ:
  180. if (aRAJDialogue[uiCount].iTextId)
  181. iTextId = aRAJDialogue[uiCount].iTextId;
  182. if (aRAJDialogue[uiCount].uiTimer)
  183. m_uiTalkTimer = aRAJDialogue[uiCount].uiTimer;
  184. break;
  185. }
  186. if (iTextId)
  187. DoScriptText(iTextId, m_creature);
  188. }
  189. void PrepareEncounter()
  190. {
  191. debug_log("SD2: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId);
  192. switch(m_uiEventId)
  193. {
  194. case EVENT_OZ:
  195. for(int i=0; i < 4; ++i)
  196. m_creature->SummonCreature(aSpawns_OZ[i].uiEntry, aSpawns_OZ[i].fPosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS);
  197. break;
  198. case EVENT_HOOD:
  199. m_creature->SummonCreature(Spawn_HOOD.uiEntry, Spawn_HOOD.fPosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS);
  200. break;
  201. case EVENT_RAJ:
  202. m_creature->SummonCreature(Spawn_RAJ.uiEntry, Spawn_RAJ.fPosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS);
  203. break;
  204. default:
  205. error_log("SD2: Barnes Opera Event - Wrong EventId set: %d", m_uiEventId);
  206. break;
  207. }
  208. m_bRaidWiped = false;
  209. }
  210. void UpdateEscortAI(const uint32 uiDiff)
  211. {
  212. if (HasEscortState(STATE_ESCORT_PAUSED))
  213. {
  214. if (m_uiTalkTimer < uiDiff)
  215. {
  216. if (m_uiTalkCount > 3)
  217. {
  218. if (Creature* pSpotlight = m_creature->GetMap()->GetCreature(m_spotlightGuid))
  219. pSpotlight->ForcedDespawn();
  220. SetEscortPaused(false);
  221. return;
  222. }
  223. Talk(m_uiTalkCount++);
  224. }
  225. else
  226. m_uiTalkTimer -= uiDiff;
  227. }
  228. if (m_bPerformanceReady)
  229. {
  230. if (!m_bRaidWiped)
  231. {
  232. if (m_uiWipeTimer < uiDiff)
  233. {
  234. Map *pMap = m_creature->GetMap();
  235. if (!pMap->IsDungeon())
  236. return;
  237. Map::PlayerList const &PlayerList = pMap->GetPlayers();
  238. if (PlayerList.isEmpty())
  239. return;
  240. m_bRaidWiped = true;
  241. for(Map::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i)
  242. {
  243. if (i->getSource()->isAlive() && !i->getSource()->isGameMaster())
  244. {
  245. m_bRaidWiped = false;
  246. break;
  247. }
  248. }
  249. if (m_bRaidWiped)
  250. EnterEvadeMode();
  251. m_uiWipeTimer = 15000;
  252. }
  253. else
  254. m_uiWipeTimer -= uiDiff;
  255. }
  256. }
  257. }
  258. };
  259. CreatureAI* GetAI_npc_barnesAI(Creature* pCreature)
  260. {
  261. return new npc_barnesAI(pCreature);
  262. }
  263. bool GossipHello_npc_barnes(Player* pPlayer, Creature* pCreature)
  264. {
  265. if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
  266. {
  267. // Check for death of Moroes and if opera event is not done already
  268. if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE)
  269. {
  270. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  271. if (pPlayer->isGameMaster()) // for GMs we add the possibility to change the event
  272. {
  273. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
  274. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
  275. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
  276. }
  277. if (npc_barnesAI* pBarnesAI = dynamic_cast<npc_barnesAI*>(pCreature->AI()))
  278. {
  279. if (!pBarnesAI->m_bRaidWiped)
  280. pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetObjectGuid());
  281. else
  282. pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetObjectGuid());
  283. return true;
  284. }
  285. }
  286. }
  287. pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetObjectGuid());
  288. return true;
  289. }
  290. bool GossipSelect_npc_barnes(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
  291. {
  292. npc_barnesAI* pBarnesAI = dynamic_cast<npc_barnesAI*>(pCreature->AI());
  293. switch(uiAction)
  294. {
  295. case GOSSIP_ACTION_INFO_DEF+1:
  296. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
  297. pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetObjectGuid());
  298. break;
  299. case GOSSIP_ACTION_INFO_DEF+2:
  300. pPlayer->CLOSE_GOSSIP_MENU();
  301. if (pBarnesAI)
  302. pBarnesAI->StartEvent();
  303. break;
  304. case GOSSIP_ACTION_INFO_DEF+3:
  305. pPlayer->CLOSE_GOSSIP_MENU();
  306. if (pBarnesAI && pPlayer->isGameMaster())
  307. pBarnesAI->m_uiEventId = EVENT_OZ;
  308. outstring_log("SD2: %s manually set Opera event to EVENT_OZ", pPlayer->GetGuidStr().c_str());
  309. break;
  310. case GOSSIP_ACTION_INFO_DEF+4:
  311. pPlayer->CLOSE_GOSSIP_MENU();
  312. if (pBarnesAI && pPlayer->isGameMaster())
  313. pBarnesAI->m_uiEventId = EVENT_HOOD;
  314. outstring_log("SD2: %s manually set Opera event to EVENT_HOOD", pPlayer->GetGuidStr().c_str());
  315. break;
  316. case GOSSIP_ACTION_INFO_DEF+5:
  317. pPlayer->CLOSE_GOSSIP_MENU();
  318. if (pBarnesAI && pPlayer->isGameMaster())
  319. pBarnesAI->m_uiEventId = EVENT_RAJ;
  320. outstring_log("SD2: %s manually set Opera event to EVENT_RAJ", pPlayer->GetGuidStr().c_str());
  321. break;
  322. }
  323. return true;
  324. }
  325. /*###
  326. # npc_berthold
  327. ####*/
  328. enum
  329. {
  330. SPELL_TELEPORT = 39567
  331. };
  332. #define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library"
  333. bool GossipHello_npc_berthold(Player* pPlayer, Creature* pCreature)
  334. {
  335. if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
  336. {
  337. // Check if Shade of Aran event is done
  338. if (pInstance->GetData(TYPE_ARAN) == DONE)
  339. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  340. }
  341. pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid());
  342. return true;
  343. }
  344. bool GossipSelect_npc_berthold(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
  345. {
  346. if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
  347. pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true);
  348. pPlayer->CLOSE_GOSSIP_MENU();
  349. return true;
  350. }
  351. void AddSC_karazhan()
  352. {
  353. Script* pNewScript;
  354. pNewScript = new Script;
  355. pNewScript->Name = "npc_barnes";
  356. pNewScript->GetAI = &GetAI_npc_barnesAI;
  357. pNewScript->pGossipHello = &GossipHello_npc_barnes;
  358. pNewScript->pGossipSelect = &GossipSelect_npc_barnes;
  359. pNewScript->RegisterSelf();
  360. pNewScript = new Script;
  361. pNewScript->Name = "npc_berthold";
  362. pNewScript->pGossipHello = &GossipHello_npc_berthold;
  363. pNewScript->pGossipSelect = &GossipSelect_npc_berthold;
  364. pNewScript->RegisterSelf();
  365. }