Advertisement
Sleinzel

Untitled

May 4th, 2011
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 46.94 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17.  
  18. #include "ObjectMgr.h"
  19. #include "ScriptMgr.h"
  20. #include "InstanceScript.h"
  21. #include "ScriptedCreature.h"
  22. #include "Map.h"
  23. #include "PoolMgr.h"
  24. #include "icecrown_citadel.h"
  25.  
  26. DoorData const doorData[] =
  27. {
  28. {GO_LORD_MARROWGAR_S_ENTRANCE, DATA_LORD_MARROWGAR, DOOR_TYPE_ROOM, BOUNDARY_N },
  29. {GO_ICEWALL, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
  30. {GO_DOODAD_ICECROWN_ICEWALL02, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
  31. {GO_ORATORY_OF_THE_DAMNED_ENTRANCE, DATA_LADY_DEATHWHISPER, DOOR_TYPE_ROOM, BOUNDARY_N },
  32. {GO_SAURFANG_S_DOOR, DATA_DEATHBRINGER_SAURFANG, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
  33. {GO_ORANGE_PLAGUE_MONSTER_ENTRANCE, DATA_FESTERGUT, DOOR_TYPE_ROOM, BOUNDARY_E },
  34. {GO_GREEN_PLAGUE_MONSTER_ENTRANCE, DATA_ROTFACE, DOOR_TYPE_ROOM, BOUNDARY_E },
  35. {GO_SCIENTIST_ENTRANCE, DATA_PROFESSOR_PUTRICIDE, DOOR_TYPE_ROOM, BOUNDARY_E },
  36. {GO_CRIMSON_HALL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_ROOM, BOUNDARY_S },
  37. {GO_BLOOD_ELF_COUNCIL_DOOR, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE, BOUNDARY_W },
  38. {GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE, BOUNDARY_E },
  39. {GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_ROOM, BOUNDARY_S },
  40. {GO_DOODAD_ICECROWN_GRATE_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
  41. {GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_ROOM, BOUNDARY_N },
  42. {GO_GREEN_DRAGON_BOSS_EXIT, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_PASSAGE, BOUNDARY_S },
  43. {GO_SINDRAGOSA_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_S },
  44. {GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_E },
  45. {GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
  46. {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SE },
  47. {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SW },
  48. {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
  49. };
  50.  
  51. // this doesnt have to only store questgivers, also can be used for related quest spawns
  52. struct WeeklyQuest
  53. {
  54. uint32 creatureEntry;
  55. uint32 questId[2]; // 10 and 25 man versions
  56. };
  57.  
  58. // when changing the content, remember to update SetData, DATA_BLOOD_QUICKENING_STATE case for NPC_ALRIN_THE_AGILE index
  59. WeeklyQuest const WeeklyQuestData[WeeklyNPCs] =
  60. {
  61. {NPC_INFILTRATOR_MINCHAR, {QUEST_DEPROGRAMMING_10, QUEST_DEPROGRAMMING_25 }}, // Deprogramming
  62. {NPC_KOR_KRON_LIEUTENANT, {QUEST_SECURING_THE_RAMPARTS_10, QUEST_SECURING_THE_RAMPARTS_25 }}, // Securing the Ramparts
  63. {NPC_ROTTING_FROST_GIANT_10, {QUEST_SECURING_THE_RAMPARTS_10, QUEST_SECURING_THE_RAMPARTS_25 }}, // Securing the Ramparts
  64. {NPC_ROTTING_FROST_GIANT_25, {QUEST_SECURING_THE_RAMPARTS_10, QUEST_SECURING_THE_RAMPARTS_25 }}, // Securing the Ramparts
  65. {NPC_ALCHEMIST_ADRIANNA, {QUEST_RESIDUE_RENDEZVOUS_10, QUEST_RESIDUE_RENDEZVOUS_25 }}, // Residue Rendezvous
  66. {NPC_ALRIN_THE_AGILE, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening
  67. {NPC_INFILTRATOR_MINCHAR_BQ, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening
  68. {NPC_MINCHAR_BEAM_STALKER, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening
  69. {NPC_VALITHRIA_DREAMWALKER_QUEST, {QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25}}, // Respite for a Tormented Soul
  70. };
  71.  
  72. class instance_icecrown_citadel : public InstanceMapScript
  73. {
  74. public:
  75. instance_icecrown_citadel() : InstanceMapScript(ICCScriptName, 631) { }
  76.  
  77. struct instance_icecrown_citadel_InstanceMapScript : public InstanceScript
  78. {
  79. instance_icecrown_citadel_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
  80. {
  81. SetBossNumber(EncounterCount);
  82. LoadDoorData(doorData);
  83. teamInInstance = 0;
  84. heroicAttempts = MaxHeroicAttempts;
  85. ladyDeathwisperElevator = 0;
  86. deathbringerSaurfang = 0;
  87. saurfangDoor = 0;
  88. saurfangEventNPC = 0;
  89. deathbringersCache = 0;
  90. saurfangTeleport = 0;
  91. plagueSigil = 0;
  92. bloodwingSigil = 0;
  93. frostwingSigil = 0;
  94. memset(putricidePipes, 0, 2*sizeof(uint64));
  95. memset(putricideGates, 0, 2*sizeof(uint64));
  96. putricideCollision = 0;
  97. festergut = 0;
  98. rotface = 0;
  99. professorPutricide = 0;
  100. putricideTable = 0;
  101. memset(bloodCouncil, 0, 3*sizeof(uint64));
  102. bloodCouncilController = 0;
  103. bloodQueenLanaThel = 0;
  104. sindragosa = 0;
  105. spinestalker = 0;
  106. rimefang = 0;
  107. frostwyrms = 0;
  108. spinestalkerTrash = 0;
  109. rimefangTrash = 0;
  110. isBonedEligible = true;
  111. isOozeDanceEligible = true;
  112. isNauseaEligible = true;
  113. isOrbWhispererEligible = true;
  114. coldflameJetsState = NOT_STARTED;
  115. bloodQuickeningState = NOT_STARTED;
  116. bloodQuickeningTimer = 0;
  117. bloodQuickeningMinutes = 0;
  118. }
  119.  
  120. void FillInitialWorldStates(WorldPacket& data)
  121. {
  122. data << uint32(WORLDSTATE_SHOW_TIMER) << uint32(bloodQuickeningState == IN_PROGRESS);
  123. data << uint32(WORLDSTATE_EXECUTION_TIME) << uint32(bloodQuickeningMinutes);
  124. data << uint32(WORLDSTATE_SHOW_ATTEMPTS) << uint32(instance->IsHeroic());
  125. data << uint32(WORLDSTATE_ATTEMPTS_REMAINING) << uint32(heroicAttempts);
  126. data << uint32(WORLDSTATE_ATTEMPTS_MAX) << uint32(MaxHeroicAttempts);
  127. }
  128.  
  129. void OnPlayerEnter(Player* player)
  130. {
  131. if (!teamInInstance)
  132. teamInInstance = player->GetTeam();
  133. }
  134.  
  135. void OnCreatureCreate(Creature* creature)
  136. {
  137. if (!teamInInstance)
  138. {
  139. Map::PlayerList const &players = instance->GetPlayers();
  140. if (!players.isEmpty())
  141. if (Player* player = players.begin()->getSource())
  142. teamInInstance = player->GetTeam();
  143. }
  144.  
  145. switch (creature->GetEntry())
  146. {
  147. case NPC_KOR_KRON_GENERAL:
  148. if (teamInInstance == ALLIANCE)
  149. creature->UpdateEntry(NPC_ALLIANCE_COMMANDER, ALLIANCE);
  150. break;
  151. case NPC_KOR_KRON_LIEUTENANT:
  152. if (teamInInstance == ALLIANCE)
  153. creature->UpdateEntry(NPC_SKYBREAKER_LIEUTENANT, ALLIANCE);
  154. break;
  155. case NPC_TORTUNOK:
  156. if (teamInInstance == ALLIANCE)
  157. creature->UpdateEntry(NPC_ALANA_MOONSTRIKE, ALLIANCE);
  158. break;
  159. case NPC_GERARDO_THE_SUAVE:
  160. if (teamInInstance == ALLIANCE)
  161. creature->UpdateEntry(NPC_TALAN_MOONSTRIKE, ALLIANCE);
  162. break;
  163. case NPC_UVLUS_BANEFIRE:
  164. if (teamInInstance == ALLIANCE)
  165. creature->UpdateEntry(NPC_MALFUS_GRIMFROST, ALLIANCE);
  166. break;
  167. case NPC_IKFIRUS_THE_VILE:
  168. if (teamInInstance == ALLIANCE)
  169. creature->UpdateEntry(NPC_YILI, ALLIANCE);
  170. break;
  171. case NPC_VOL_GUK:
  172. if (teamInInstance == ALLIANCE)
  173. creature->UpdateEntry(NPC_JEDEBIA, ALLIANCE);
  174. break;
  175. case NPC_HARAGG_THE_UNSEEN:
  176. if (teamInInstance == ALLIANCE)
  177. creature->UpdateEntry(NPC_NIBY_THE_ALMIGHTY, ALLIANCE);
  178. break;
  179. case NPC_GARROSH_HELLSCREAM:
  180. if (teamInInstance == ALLIANCE)
  181. creature->UpdateEntry(NPC_KING_VARIAN_WRYNN, ALLIANCE);
  182. break;
  183. case NPC_DEATHBRINGER_SAURFANG:
  184. deathbringerSaurfang = creature->GetGUID();
  185. break;
  186. case NPC_SE_HIGH_OVERLORD_SAURFANG:
  187. if (teamInInstance == ALLIANCE)
  188. creature->UpdateEntry(NPC_SE_MURADIN_BRONZEBEARD, ALLIANCE, creature->GetCreatureData());
  189. case NPC_SE_MURADIN_BRONZEBEARD:
  190. saurfangEventNPC = creature->GetGUID();
  191. creature->LastUsedScriptID = creature->GetScriptId();
  192. break;
  193. case NPC_SE_KOR_KRON_REAVER:
  194. if (teamInInstance == ALLIANCE)
  195. creature->UpdateEntry(NPC_SE_SKYBREAKER_MARINE, ALLIANCE);
  196. break;
  197. case NPC_FROST_FREEZE_TRAP:
  198. coldflameJets.insert(creature->GetGUID());
  199. break;
  200. case NPC_FESTERGUT:
  201. festergut = creature->GetGUID();
  202. break;
  203. case NPC_ROTFACE:
  204. rotface = creature->GetGUID();
  205. break;
  206. case NPC_PROFESSOR_PUTRICIDE:
  207. professorPutricide = creature->GetGUID();
  208. break;
  209. case NPC_PRINCE_KELESETH:
  210. bloodCouncil[0] = creature->GetGUID();
  211. break;
  212. case NPC_PRINCE_TALDARAM:
  213. bloodCouncil[1] = creature->GetGUID();
  214. break;
  215. case NPC_PRINCE_VALANAR:
  216. bloodCouncil[2] = creature->GetGUID();
  217. break;
  218. case NPC_BLOOD_ORB_CONTROLLER:
  219. bloodCouncilController = creature->GetGUID();
  220. break;
  221. case NPC_BLOOD_QUEEN_LANA_THEL:
  222. bloodQueenLanaThel = creature->GetGUID();
  223. break;
  224. case NPC_SINDRAGOSA:
  225. sindragosa = creature->GetGUID();
  226. break;
  227. case NPC_SPINESTALKER:
  228. spinestalker = creature->GetGUID();
  229. if (!creature->isDead())
  230. ++frostwyrms;
  231. break;
  232. case NPC_RIMEFANG:
  233. rimefang = creature->GetGUID();
  234. if (!creature->isDead())
  235. ++frostwyrms;
  236. break;
  237. default:
  238. break;
  239. }
  240. }
  241.  
  242. // Weekly quest spawn prevention
  243. uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data)
  244. {
  245. uint32 entry = data->id;
  246. switch (entry)
  247. {
  248. case NPC_INFILTRATOR_MINCHAR:
  249. case NPC_KOR_KRON_LIEUTENANT:
  250. case NPC_ALCHEMIST_ADRIANNA:
  251. case NPC_ALRIN_THE_AGILE:
  252. case NPC_INFILTRATOR_MINCHAR_BQ:
  253. case NPC_MINCHAR_BEAM_STALKER:
  254. case NPC_VALITHRIA_DREAMWALKER_QUEST:
  255. {
  256. for (uint8 questIndex = 0; questIndex < WeeklyNPCs; ++questIndex)
  257. {
  258. if (WeeklyQuestData[questIndex].creatureEntry == entry)
  259. {
  260. uint8 diffIndex = uint8(instance->GetSpawnMode() & 1);
  261. if (!sPoolMgr->IsSpawnedObject<Quest>(WeeklyQuestData[questIndex].questId[diffIndex]))
  262. entry = 0;
  263. break;
  264. }
  265. }
  266. break;
  267. }
  268. default:
  269. break;
  270. }
  271.  
  272. return entry;
  273. }
  274.  
  275. void OnCreatureRemove(Creature* creature)
  276. {
  277. if (creature->GetEntry() == NPC_FROST_FREEZE_TRAP)
  278. coldflameJets.erase(creature->GetGUID());
  279. }
  280.  
  281. void OnGameObjectCreate(GameObject* go)
  282. {
  283. switch (go->GetEntry())
  284. {
  285. case GO_DOODAD_ICECROWN_ICEWALL02:
  286. case GO_ICEWALL:
  287. case GO_LORD_MARROWGAR_S_ENTRANCE:
  288. case GO_ORATORY_OF_THE_DAMNED_ENTRANCE:
  289. case GO_ORANGE_PLAGUE_MONSTER_ENTRANCE:
  290. case GO_GREEN_PLAGUE_MONSTER_ENTRANCE:
  291. case GO_SCIENTIST_ENTRANCE:
  292. case GO_CRIMSON_HALL_DOOR:
  293. case GO_BLOOD_ELF_COUNCIL_DOOR:
  294. case GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT:
  295. case GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01:
  296. case GO_DOODAD_ICECROWN_GRATE_01:
  297. case GO_GREEN_DRAGON_BOSS_ENTRANCE:
  298. case GO_GREEN_DRAGON_BOSS_EXIT:
  299. case GO_SINDRAGOSA_ENTRANCE_DOOR:
  300. case GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR:
  301. case GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR:
  302. case GO_ICE_WALL:
  303. AddDoor(go, true);
  304. break;
  305. case GO_LADY_DEATHWHISPER_ELEVATOR:
  306. ladyDeathwisperElevator = go->GetGUID();
  307. if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE)
  308. {
  309. go->SetUInt32Value(GAMEOBJECT_LEVEL, 0);
  310. go->SetGoState(GO_STATE_READY);
  311. }
  312. break;
  313. case GO_SAURFANG_S_DOOR:
  314. saurfangDoor = go->GetGUID();
  315. AddDoor(go, true);
  316. break;
  317. case GO_DEATHBRINGER_S_CACHE_10N:
  318. case GO_DEATHBRINGER_S_CACHE_25N:
  319. case GO_DEATHBRINGER_S_CACHE_10H:
  320. case GO_DEATHBRINGER_S_CACHE_25H:
  321. deathbringersCache = go->GetGUID();
  322. break;
  323. case GO_SCOURGE_TRANSPORTER_SAURFANG:
  324. saurfangTeleport = go->GetGUID();
  325. break;
  326. case GO_PLAGUE_SIGIL:
  327. plagueSigil = go->GetGUID();
  328. if (GetBossState(DATA_PROFESSOR_PUTRICIDE) == DONE)
  329. HandleGameObject(plagueSigil, false, go);
  330. break;
  331. case GO_BLOODWING_SIGIL:
  332. bloodwingSigil = go->GetGUID();
  333. if (GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == DONE)
  334. HandleGameObject(bloodwingSigil, false, go);
  335. break;
  336. case GO_SIGIL_OF_THE_FROSTWING:
  337. frostwingSigil = go->GetGUID();
  338. if (GetBossState(DATA_SINDRAGOSA) == DONE)
  339. HandleGameObject(frostwingSigil, false, go);
  340. break;
  341. case GO_SCIENTIST_AIRLOCK_DOOR_COLLISION:
  342. putricideCollision = go->GetGUID();
  343. if (GetBossState(DATA_FESTERGUT) == DONE && GetBossState(DATA_ROTFACE) == DONE)
  344. HandleGameObject(putricideCollision, true, go);
  345. break;
  346. case GO_SCIENTIST_AIRLOCK_DOOR_ORANGE:
  347. putricideGates[0] = go->GetGUID();
  348. if (GetBossState(DATA_FESTERGUT) == DONE && GetBossState(DATA_ROTFACE) == DONE)
  349. go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
  350. else if (GetBossState(DATA_FESTERGUT) == DONE)
  351. HandleGameObject(putricideGates[1], false, go);
  352. break;
  353. case GO_SCIENTIST_AIRLOCK_DOOR_GREEN:
  354. putricideGates[1] = go->GetGUID();
  355. if (GetBossState(DATA_ROTFACE) == DONE && GetBossState(DATA_FESTERGUT) == DONE)
  356. go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
  357. else if (GetBossState(DATA_ROTFACE) == DONE)
  358. HandleGameObject(putricideGates[1], false, go);
  359. break;
  360. case GO_DOODAD_ICECROWN_ORANGETUBES02:
  361. putricidePipes[0] = go->GetGUID();
  362. if (GetBossState(DATA_FESTERGUT) == DONE)
  363. HandleGameObject(putricidePipes[0], true, go);
  364. break;
  365. case GO_DOODAD_ICECROWN_GREENTUBES02:
  366. putricidePipes[1] = go->GetGUID();
  367. if (GetBossState(DATA_ROTFACE) == DONE)
  368. HandleGameObject(putricidePipes[1], true, go);
  369. break;
  370. case GO_DRINK_ME:
  371. putricideTable = go->GetGUID();
  372. break;
  373. default:
  374. break;
  375. }
  376. }
  377.  
  378. void OnGameObjectRemove(GameObject* go)
  379. {
  380. switch (go->GetEntry())
  381. {
  382. case GO_DOODAD_ICECROWN_ICEWALL02:
  383. case GO_ICEWALL:
  384. case GO_LORD_MARROWGAR_S_ENTRANCE:
  385. case GO_ORATORY_OF_THE_DAMNED_ENTRANCE:
  386. case GO_SAURFANG_S_DOOR:
  387. case GO_ORANGE_PLAGUE_MONSTER_ENTRANCE:
  388. case GO_GREEN_PLAGUE_MONSTER_ENTRANCE:
  389. case GO_SCIENTIST_ENTRANCE:
  390. case GO_CRIMSON_HALL_DOOR:
  391. case GO_BLOOD_ELF_COUNCIL_DOOR:
  392. case GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT:
  393. case GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01:
  394. case GO_DOODAD_ICECROWN_GRATE_01:
  395. case GO_GREEN_DRAGON_BOSS_ENTRANCE:
  396. case GO_GREEN_DRAGON_BOSS_EXIT:
  397. case GO_SINDRAGOSA_ENTRANCE_DOOR:
  398. case GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR:
  399. case GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR:
  400. case GO_ICE_WALL:
  401. AddDoor(go, false);
  402. break;
  403. default:
  404. break;
  405. }
  406. }
  407.  
  408. uint32 GetData(uint32 type)
  409. {
  410. switch (type)
  411. {
  412. case DATA_SINDRAGOSA_FROSTWYRMS:
  413. return frostwyrms;
  414. case DATA_SPINESTALKER:
  415. return spinestalkerTrash;
  416. case DATA_RIMEFANG:
  417. return rimefangTrash;
  418. case DATA_COLDFLAME_JETS:
  419. return coldflameJetsState;
  420. case DATA_TEAM_IN_INSTANCE:
  421. return teamInInstance;
  422. case DATA_BLOOD_QUICKENING_STATE:
  423. return bloodQuickeningState;
  424. case DATA_HEROIC_ATTEMPTS:
  425. return heroicAttempts;
  426. default:
  427. break;
  428. }
  429.  
  430. return 0;
  431. }
  432.  
  433. uint64 GetData64(uint32 type)
  434. {
  435. switch (type)
  436. {
  437. case DATA_DEATHBRINGER_SAURFANG:
  438. return deathbringerSaurfang;
  439. case DATA_SAURFANG_EVENT_NPC:
  440. return saurfangEventNPC;
  441. case GO_SAURFANG_S_DOOR:
  442. return saurfangDoor;
  443. case GO_SCOURGE_TRANSPORTER_SAURFANG:
  444. return saurfangTeleport;
  445. case DATA_FESTERGUT:
  446. return festergut;
  447. case DATA_ROTFACE:
  448. return rotface;
  449. case DATA_PROFESSOR_PUTRICIDE:
  450. return professorPutricide;
  451. case DATA_PUTRICIDE_TABLE:
  452. return putricideTable;
  453. case DATA_PRINCE_KELESETH_GUID:
  454. return bloodCouncil[0];
  455. case DATA_PRINCE_TALDARAM_GUID:
  456. return bloodCouncil[1];
  457. case DATA_PRINCE_VALANAR_GUID:
  458. return bloodCouncil[2];
  459. case DATA_BLOOD_PRINCES_CONTROL:
  460. return bloodCouncilController;
  461. case DATA_BLOOD_QUEEN_LANA_THEL:
  462. return bloodQueenLanaThel;
  463. case DATA_SINDRAGOSA:
  464. return sindragosa;
  465. case DATA_SPINESTALKER:
  466. return spinestalker;
  467. case DATA_RIMEFANG:
  468. return rimefang;
  469. default:
  470. break;
  471. }
  472.  
  473. return 0;
  474. }
  475.  
  476. bool SetBossState(uint32 type, EncounterState state)
  477. {
  478. if (!InstanceScript::SetBossState(type, state))
  479. return false;
  480.  
  481. switch (type)
  482. {
  483. case DATA_LADY_DEATHWHISPER:
  484. SetBossState(DATA_GUNSHIP_EVENT, state); // TEMP HACK UNTIL GUNSHIP SCRIPTED
  485. if (state == DONE)
  486. {
  487. if (GameObject* elevator = instance->GetGameObject(ladyDeathwisperElevator))
  488. {
  489. elevator->SetUInt32Value(GAMEOBJECT_LEVEL, 0);
  490. elevator->SetGoState(GO_STATE_READY);
  491. }
  492. }
  493. break;
  494. case DATA_DEATHBRINGER_SAURFANG:
  495. switch (state)
  496. {
  497. case DONE:
  498. DoRespawnGameObject(deathbringersCache, 7*DAY);
  499. case NOT_STARTED:
  500. if (GameObject* teleporter = instance->GetGameObject(saurfangTeleport))
  501. {
  502. HandleGameObject(saurfangTeleport, true, teleporter);
  503. teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
  504. }
  505. break;
  506. default:
  507. break;
  508. }
  509. break;
  510. case DATA_FESTERGUT:
  511. if (state == DONE)
  512. {
  513. if (GetBossState(DATA_ROTFACE) == DONE)
  514. {
  515. HandleGameObject(putricideCollision, true);
  516. if (GameObject* go = instance->GetGameObject(putricideGates[0]))
  517. go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
  518. if (GameObject* go = instance->GetGameObject(putricideGates[1]))
  519. go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
  520. }
  521. else
  522. HandleGameObject(putricideGates[0], false);
  523. HandleGameObject(putricidePipes[0], true);
  524. }
  525. break;
  526. case DATA_ROTFACE:
  527. if (state == DONE)
  528. {
  529. if (GetBossState(DATA_FESTERGUT) == DONE)
  530. {
  531. HandleGameObject(putricideCollision, true);
  532. if (GameObject* go = instance->GetGameObject(putricideGates[0]))
  533. go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
  534. if (GameObject* go = instance->GetGameObject(putricideGates[1]))
  535. go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
  536. }
  537. else
  538. HandleGameObject(putricideGates[1], false);
  539. HandleGameObject(putricidePipes[1], true);
  540. }
  541. break;
  542. case DATA_PROFESSOR_PUTRICIDE:
  543. HandleGameObject(plagueSigil, state != DONE);
  544. if (instance->IsHeroic())
  545. {
  546. if (state == FAIL && heroicAttempts)
  547. {
  548. --heroicAttempts;
  549. DoUpdateWorldState(WORLDSTATE_ATTEMPTS_REMAINING, heroicAttempts);
  550. if (!heroicAttempts)
  551. if (Creature* putricide = instance->GetCreature(professorPutricide))
  552. putricide->DespawnOrUnsummon();
  553. }
  554. }
  555. break;
  556. case DATA_BLOOD_QUEEN_LANA_THEL:
  557. HandleGameObject(bloodwingSigil, state != DONE);
  558. if (instance->IsHeroic())
  559. {
  560. if (state == FAIL && heroicAttempts)
  561. {
  562. --heroicAttempts;
  563. DoUpdateWorldState(WORLDSTATE_ATTEMPTS_REMAINING, heroicAttempts);
  564. if (!heroicAttempts)
  565. if (Creature* bq = instance->GetCreature(bloodQueenLanaThel))
  566. bq->DespawnOrUnsummon();
  567. }
  568. }
  569. break;
  570. case DATA_VALITHRIA_DREAMWALKER:
  571. break;
  572. case DATA_SINDRAGOSA:
  573. HandleGameObject(frostwingSigil, state != DONE);
  574. if (instance->IsHeroic())
  575. {
  576. if (state == FAIL && heroicAttempts)
  577. {
  578. --heroicAttempts;
  579. DoUpdateWorldState(WORLDSTATE_ATTEMPTS_REMAINING, heroicAttempts);
  580. if (!heroicAttempts)
  581. if (Creature* sindra = instance->GetCreature(sindragosa))
  582. sindra->DespawnOrUnsummon();
  583. }
  584. }
  585. break;
  586. case DATA_THE_LICH_KING:
  587. break;
  588. default:
  589. break;
  590. }
  591.  
  592. return true;
  593. }
  594.  
  595. void SetData(uint32 type, uint32 data)
  596. {
  597. switch (type)
  598. {
  599. case DATA_BONED_ACHIEVEMENT:
  600. isBonedEligible = data ? true : false;
  601. break;
  602. case DATA_OOZE_DANCE_ACHIEVEMENT:
  603. isOozeDanceEligible = data ? true : false;
  604. break;
  605. case DATA_NAUSEA_ACHIEVEMENT:
  606. isNauseaEligible = data ? true : false;
  607. break;
  608. case DATA_ORB_WHISPERER_ACHIEVEMENT:
  609. isOrbWhispererEligible = data ? true : false;
  610. break;
  611. case DATA_SINDRAGOSA_FROSTWYRMS:
  612. {
  613. if (frostwyrms == 255)
  614. return;
  615.  
  616. if (instance->IsHeroic() && !heroicAttempts)
  617. return;
  618.  
  619. if (GetBossState(DATA_SINDRAGOSA) != DONE)
  620. return;
  621.  
  622. switch (data)
  623. {
  624. case 0:
  625. if (frostwyrms)
  626. {
  627. --frostwyrms;
  628. if (!frostwyrms)
  629. {
  630. instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY());
  631. if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos))
  632. boss->AI()->DoAction(ACTION_START_FROSTWYRM);
  633. }
  634. }
  635. break;
  636. case 1:
  637. ++frostwyrms;
  638. break;
  639. default:
  640. frostwyrms = data;
  641. break;
  642. }
  643. break;
  644. }
  645. case DATA_SPINESTALKER:
  646. {
  647. if (spinestalkerTrash == 255)
  648. return;
  649.  
  650. switch (data)
  651. {
  652. case 0:
  653. if (spinestalkerTrash)
  654. {
  655. --spinestalkerTrash;
  656. if (!spinestalkerTrash)
  657. if (Creature* spinestalk = instance->GetCreature(spinestalker))
  658. spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM);
  659. }
  660. break;
  661. case 1:
  662. ++spinestalkerTrash;
  663. break;
  664. default:
  665. spinestalkerTrash = data;
  666. break;
  667. }
  668. break;
  669. }
  670. case DATA_RIMEFANG:
  671. {
  672. if (rimefangTrash == 255)
  673. return;
  674.  
  675. switch (data)
  676. {
  677. case 0:
  678. if (rimefangTrash)
  679. {
  680. --rimefangTrash;
  681. if (!rimefangTrash)
  682. if (Creature* rime = instance->GetCreature(rimefang))
  683. rime->AI()->DoAction(ACTION_START_FROSTWYRM);
  684. }
  685. break;
  686. case 1:
  687. ++rimefangTrash;
  688. break;
  689. default:
  690. rimefangTrash = data;
  691. break;
  692. }
  693. break;
  694. }
  695. case DATA_COLDFLAME_JETS:
  696. coldflameJetsState = data;
  697. if (coldflameJetsState == DONE)
  698. {
  699. SaveToDB();
  700. for (std::set<uint64>::iterator itr = coldflameJets.begin(); itr != coldflameJets.end(); ++itr)
  701. if (Creature* trap = instance->GetCreature(*itr))
  702. trap->AI()->DoAction(ACTION_STOP_TRAPS);
  703. }
  704. break;
  705. case DATA_BLOOD_QUICKENING_STATE:
  706. {
  707. // skip if nothing changes
  708. if (bloodQuickeningState == data)
  709. break;
  710.  
  711. // 5 is the index of Blood Quickening
  712. if (!sPoolMgr->IsSpawnedObject<Quest>(WeeklyQuestData[5].questId[instance->GetSpawnMode() & 1]))
  713. break;
  714.  
  715. switch (data)
  716. {
  717. case IN_PROGRESS:
  718. bloodQuickeningTimer = 60000;
  719. bloodQuickeningMinutes = 30;
  720. DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
  721. DoUpdateWorldState(WORLDSTATE_EXECUTION_TIME, bloodQuickeningMinutes);
  722. break;
  723. case DONE:
  724. bloodQuickeningTimer = 0;
  725. bloodQuickeningMinutes = 0;
  726. DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
  727. break;
  728. default:
  729. break;
  730. }
  731.  
  732. bloodQuickeningState = data;
  733. SaveToDB();
  734. break;
  735. }
  736. default:
  737. break;
  738. }
  739. }
  740.  
  741. bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/)
  742. {
  743. switch (criteria_id)
  744. {
  745. case CRITERIA_BONED_10N:
  746. case CRITERIA_BONED_25N:
  747. case CRITERIA_BONED_10H:
  748. case CRITERIA_BONED_25H:
  749. return isBonedEligible;
  750. case CRITERIA_DANCES_WITH_OOZES_10N:
  751. case CRITERIA_DANCES_WITH_OOZES_25N:
  752. case CRITERIA_DANCES_WITH_OOZES_10H:
  753. case CRITERIA_DANCES_WITH_OOZES_25H:
  754. return isOozeDanceEligible;
  755. case CRITERIA_NAUSEA_10N:
  756. case CRITERIA_NAUSEA_25N:
  757. case CRITERIA_NAUSEA_10H:
  758. case CRITERIA_NAUSEA_25H:
  759. return isNauseaEligible;
  760. case CRITERIA_ORB_WHISPERER_10N:
  761. case CRITERIA_ORB_WHISPERER_25N:
  762. case CRITERIA_ORB_WHISPERER_10H:
  763. case CRITERIA_ORB_WHISPERER_25H:
  764. return isOrbWhispererEligible;
  765. // Only one criteria for both modes, need to do it like this
  766. case CRITERIA_KILL_LANA_THEL_10M:
  767. case CRITERIA_ONCE_BITTEN_TWICE_SHY_10N:
  768. case CRITERIA_ONCE_BITTEN_TWICE_SHY_10V:
  769. return CAST_INST(InstanceMap, instance)->GetMaxPlayers() == 10;
  770. case CRITERIA_KILL_LANA_THEL_25M:
  771. case CRITERIA_ONCE_BITTEN_TWICE_SHY_25N:
  772. case CRITERIA_ONCE_BITTEN_TWICE_SHY_25V:
  773. return CAST_INST(InstanceMap, instance)->GetMaxPlayers() == 25;
  774. default:
  775. break;
  776. }
  777.  
  778. return false;
  779. }
  780.  
  781. bool CheckRequiredBosses(uint32 bossId, Player const* player = NULL) const
  782. {
  783. if (player && player->isGameMaster())
  784. return true;
  785.  
  786. switch (bossId)
  787. {
  788. case DATA_THE_LICH_KING:
  789. if (!CheckPlagueworks(bossId))
  790. return false;
  791. if (!CheckCrimsonHalls(bossId))
  792. return false;
  793. if (!CheckFrostwingHalls(bossId))
  794. return false;
  795. break;
  796. case DATA_SINDRAGOSA:
  797. case DATA_VALITHRIA_DREAMWALKER:
  798. if (!CheckFrostwingHalls(bossId))
  799. return false;
  800. break;
  801. case DATA_BLOOD_QUEEN_LANA_THEL:
  802. case DATA_BLOOD_PRINCE_COUNCIL:
  803. if (!CheckCrimsonHalls(bossId))
  804. return false;
  805. break;
  806. case DATA_FESTERGUT:
  807. case DATA_ROTFACE:
  808. case DATA_PROFESSOR_PUTRICIDE:
  809. if (!CheckPlagueworks(bossId))
  810. return false;
  811. break;
  812. default:
  813. break;
  814. }
  815.  
  816. if (!CheckLowerSpire(bossId))
  817. return false;
  818.  
  819. return true;
  820. }
  821.  
  822. bool CheckPlagueworks(uint32 bossId) const
  823. {
  824. switch (bossId)
  825. {
  826. case DATA_THE_LICH_KING:
  827. if (GetBossState(DATA_PROFESSOR_PUTRICIDE) != DONE)
  828. return false;
  829. // no break
  830. case DATA_PROFESSOR_PUTRICIDE:
  831. if (GetBossState(DATA_FESTERGUT) != DONE || GetBossState(DATA_ROTFACE) != DONE)
  832. return false;
  833. break;
  834. default:
  835. break;
  836. }
  837.  
  838. return true;
  839. }
  840.  
  841. bool CheckCrimsonHalls(uint32 bossId) const
  842. {
  843. switch (bossId)
  844. {
  845. case DATA_THE_LICH_KING:
  846. if (GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) != DONE)
  847. return false;
  848. // no break
  849. case DATA_BLOOD_QUEEN_LANA_THEL:
  850. if (GetBossState(DATA_BLOOD_PRINCE_COUNCIL) != DONE)
  851. return false;
  852. break;
  853. default:
  854. break;
  855. }
  856.  
  857. return true;
  858. }
  859.  
  860. bool CheckFrostwingHalls(uint32 bossId) const
  861. {
  862. switch (bossId)
  863. {
  864. case DATA_THE_LICH_KING:
  865. if (GetBossState(DATA_SINDRAGOSA) != DONE)
  866. return false;
  867. // no break
  868. case DATA_SINDRAGOSA:
  869. //if (GetBossState(DATA_VALITHRIA_DREAMWALKER) != DONE)
  870. // return false;
  871. break;
  872. default:
  873. break;
  874. }
  875.  
  876. return true;
  877. }
  878.  
  879. bool CheckLowerSpire(uint32 bossId) const
  880. {
  881. switch (bossId)
  882. {
  883. case DATA_THE_LICH_KING:
  884. case DATA_SINDRAGOSA:
  885. case DATA_BLOOD_QUEEN_LANA_THEL:
  886. case DATA_PROFESSOR_PUTRICIDE:
  887. case DATA_VALITHRIA_DREAMWALKER:
  888. case DATA_BLOOD_PRINCE_COUNCIL:
  889. case DATA_ROTFACE:
  890. case DATA_FESTERGUT:
  891. if (GetBossState(DATA_DEATHBRINGER_SAURFANG) != DONE)
  892. return false;
  893. // no break
  894. case DATA_DEATHBRINGER_SAURFANG:
  895. if (GetBossState(DATA_GUNSHIP_EVENT) != DONE)
  896. return false;
  897. // no break
  898. case DATA_GUNSHIP_EVENT:
  899. if (GetBossState(DATA_LADY_DEATHWHISPER) != DONE)
  900. return false;
  901. // no break
  902. case DATA_LADY_DEATHWHISPER:
  903. if (GetBossState(DATA_LORD_MARROWGAR) != DONE)
  904. return false;
  905. // no break
  906. case DATA_LORD_MARROWGAR:
  907. default:
  908. break;
  909. }
  910.  
  911. return true;
  912. }
  913.  
  914. std::string GetSaveData()
  915. {
  916. OUT_SAVE_INST_DATA;
  917.  
  918. std::ostringstream saveStream;
  919. saveStream << "I C " << GetBossSaveData() << coldflameJetsState
  920. << " " << bloodQuickeningState << " " << bloodQuickeningMinutes;
  921.  
  922. OUT_SAVE_INST_DATA_COMPLETE;
  923. return saveStream.str();
  924. }
  925.  
  926. void Load(const char* str)
  927. {
  928. if (!str)
  929. {
  930. OUT_LOAD_INST_DATA_FAIL;
  931. return;
  932. }
  933.  
  934. OUT_LOAD_INST_DATA(str);
  935.  
  936. char dataHead1, dataHead2;
  937.  
  938. std::istringstream loadStream(str);
  939. loadStream >> dataHead1 >> dataHead2;
  940.  
  941. if (dataHead1 == 'I' && dataHead2 == 'C')
  942. {
  943. for (uint32 i = 0; i < EncounterCount; ++i)
  944. {
  945. uint32 tmpState;
  946. loadStream >> tmpState;
  947. if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
  948. tmpState = NOT_STARTED;
  949. SetBossState(i, EncounterState(tmpState));
  950. }
  951.  
  952. uint32 temp = 0;
  953. loadStream >> temp;
  954. coldflameJetsState = temp ? DONE : NOT_STARTED;
  955. temp = 0;
  956. loadStream >> temp;
  957. bloodQuickeningState = temp ? DONE : NOT_STARTED; // DONE means finished (not success/fail)
  958. loadStream >> bloodQuickeningMinutes;
  959. }
  960. else
  961. OUT_LOAD_INST_DATA_FAIL;
  962.  
  963. OUT_LOAD_INST_DATA_COMPLETE;
  964. }
  965.  
  966. void Update(uint32 diff)
  967. {
  968. if (bloodQuickeningState == IN_PROGRESS)
  969. {
  970. if (bloodQuickeningTimer <= diff)
  971. {
  972. --bloodQuickeningMinutes;
  973. bloodQuickeningTimer = 60000;
  974. if (bloodQuickeningMinutes)
  975. {
  976. DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
  977. DoUpdateWorldState(WORLDSTATE_EXECUTION_TIME, bloodQuickeningMinutes);
  978. }
  979. else
  980. {
  981. bloodQuickeningState = DONE;
  982. DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
  983. if (Creature* bq = instance->GetCreature(bloodQueenLanaThel))
  984. bq->AI()->DoAction(ACTION_KILL_MINCHAR);
  985. }
  986. SaveToDB();
  987. }
  988. else
  989. bloodQuickeningTimer -= diff;
  990. }
  991. }
  992.  
  993. private:
  994. std::set<uint64> coldflameJets;
  995. uint64 ladyDeathwisperElevator;
  996. uint64 deathbringerSaurfang;
  997. uint64 saurfangDoor;
  998. uint64 saurfangEventNPC; // Muradin Bronzebeard or High Overlord Saurfang
  999. uint64 deathbringersCache;
  1000. uint64 saurfangTeleport;
  1001. uint64 plagueSigil;
  1002. uint64 bloodwingSigil;
  1003. uint64 frostwingSigil;
  1004. uint64 putricidePipes[2];
  1005. uint64 putricideGates[2];
  1006. uint64 putricideCollision;
  1007. uint64 festergut;
  1008. uint64 rotface;
  1009. uint64 professorPutricide;
  1010. uint64 putricideTable;
  1011. uint64 bloodCouncil[3];
  1012. uint64 bloodCouncilController;
  1013. uint64 bloodQueenLanaThel;
  1014. uint64 sindragosa;
  1015. uint64 spinestalker;
  1016. uint64 rimefang;
  1017. uint32 teamInInstance;
  1018. uint32 bloodQuickeningTimer;
  1019. uint32 coldflameJetsState;
  1020. uint32 frostwyrms;
  1021. uint32 spinestalkerTrash;
  1022. uint32 rimefangTrash;
  1023. uint32 bloodQuickeningState;
  1024. uint16 heroicAttempts;
  1025. uint16 bloodQuickeningMinutes;
  1026. bool isBonedEligible;
  1027. bool isOozeDanceEligible;
  1028. bool isNauseaEligible;
  1029. bool isOrbWhispererEligible;
  1030. };
  1031.  
  1032. InstanceScript* GetInstanceScript(InstanceMap* map) const
  1033. {
  1034. return new instance_icecrown_citadel_InstanceMapScript(map);
  1035. }
  1036. };
  1037.  
  1038. void AddSC_instance_icecrown_citadel()
  1039. {
  1040. new instance_icecrown_citadel();
  1041. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement