TowerOfNaia.java 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437
  1. /*
  2. * Copyright (C) 2004-2014 L2J DataPack
  3. *
  4. * This file is part of L2J DataPack.
  5. *
  6. * L2J DataPack is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J DataPack is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package hellbound.TowerOfNaia;
  20. import java.util.Arrays;
  21. import java.util.HashMap;
  22. import java.util.Iterator;
  23. import java.util.List;
  24. import java.util.Map;
  25. import javolution.util.FastList;
  26. import javolution.util.FastMap;
  27. import com.l2jserver.gameserver.ThreadPoolManager;
  28. import com.l2jserver.gameserver.ai.CtrlIntention;
  29. import com.l2jserver.gameserver.datatables.DoorTable;
  30. import com.l2jserver.gameserver.datatables.SkillData;
  31. import com.l2jserver.gameserver.instancemanager.GlobalVariablesManager;
  32. import com.l2jserver.gameserver.instancemanager.ZoneManager;
  33. import com.l2jserver.gameserver.model.L2Party;
  34. import com.l2jserver.gameserver.model.Location;
  35. import com.l2jserver.gameserver.model.actor.L2Npc;
  36. import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
  37. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  38. import com.l2jserver.gameserver.model.quest.Quest;
  39. import com.l2jserver.gameserver.model.skills.Skill;
  40. import com.l2jserver.gameserver.model.zone.L2ZoneType;
  41. import com.l2jserver.gameserver.network.NpcStringId;
  42. import com.l2jserver.gameserver.network.SystemMessageId;
  43. import com.l2jserver.gameserver.network.clientpackets.Say2;
  44. import com.l2jserver.gameserver.network.serverpackets.NpcSay;
  45. import com.l2jserver.gameserver.util.MinionList;
  46. import com.l2jserver.gameserver.util.Util;
  47. /**
  48. * @author GKR
  49. */
  50. public class TowerOfNaia extends Quest
  51. {
  52. // Challenge states
  53. private static final int STATE_SPORE_CHALLENGE_IN_PROGRESS = 1;
  54. private static final int STATE_SPORE_CHALLENGE_SUCCESSFULL = 2;
  55. private static final int STATE_SPORE_IDLE_TOO_LONG = 3;
  56. // Some constants
  57. private static final int SELF_DESPAWN_LIMIT = 600; // Challenge discontinues after 600 self-despawns by timer
  58. private static final int ELEMENT_INDEX_LIMIT = 120; // Epidos spawns when index reaches 120 points
  59. private static final int LOCK = 18491;
  60. private static final int CONTROLLER = 18492;
  61. private static final int ROOM_MANAGER_FIRST = 18494;
  62. private static final int ROOM_MANAGER_LAST = 18505;
  63. private static final int MUTATED_ELPY = 25604;
  64. private static final int SPORE_BASIC = 25613;
  65. private static final int SPORE_FIRE = 25605;
  66. private static final int SPORE_WATER = 25606;
  67. private static final int SPORE_WIND = 25607;
  68. private static final int SPORE_EARTH = 25608;
  69. private static final int DWARVEN_GHOST = 32370;
  70. private static final int[] EPIDOSES =
  71. {
  72. 25610,
  73. 25609,
  74. 25612,
  75. 25611
  76. }; // Order is important!
  77. private static final int[] TOWER_MONSTERS =
  78. {
  79. 18490,
  80. 22393,
  81. 22394,
  82. 22395,
  83. 22411,
  84. 22412,
  85. 22413,
  86. 22439,
  87. 22440,
  88. 22441,
  89. 22442
  90. };
  91. private static final int[] ELEMENTS =
  92. {
  93. 25605,
  94. 25606,
  95. 25607,
  96. 25608
  97. };
  98. private static final int[] OPPOSITE_ELEMENTS =
  99. {
  100. 25606,
  101. 25605,
  102. 25608,
  103. 25607
  104. };
  105. private static final String[] ELEMENTS_NAME =
  106. {
  107. "Fire",
  108. "Water",
  109. "Wind",
  110. "Earth"
  111. };
  112. private static final int[][] SPORES_MOVE_POINTS =
  113. {
  114. {
  115. -46080,
  116. 246368,
  117. -14183
  118. },
  119. {
  120. -44816,
  121. 246368,
  122. -14183
  123. },
  124. {
  125. -44224,
  126. 247440,
  127. -14184
  128. },
  129. {
  130. -44896,
  131. 248464,
  132. -14183
  133. },
  134. {
  135. -46064,
  136. 248544,
  137. -14183
  138. },
  139. {
  140. -46720,
  141. 247424,
  142. -14183
  143. }
  144. };
  145. private static final int[][] SPORES_MERGE_POSITION =
  146. {
  147. {
  148. -45488,
  149. 246768,
  150. -14183
  151. },
  152. {
  153. -44767,
  154. 247419,
  155. -14183
  156. },
  157. {
  158. -46207,
  159. 247417,
  160. -14183
  161. },
  162. {
  163. -45462,
  164. 248174,
  165. -14183
  166. }
  167. };
  168. private static final NpcStringId[] SPORES_NPCSTRING_ID =
  169. {
  170. NpcStringId.ITS_S1,
  171. NpcStringId.S1_IS_STRONG,
  172. NpcStringId.ITS_ALWAYS_S1,
  173. NpcStringId.S1_WONT_DO
  174. };
  175. private static Map<Integer, int[]> DOORS = new HashMap<>();
  176. private static Map<Integer, Integer> ZONES = new HashMap<>();
  177. private static Map<Integer, int[][]> SPAWNS = new HashMap<>();
  178. private L2MonsterInstance _lock;
  179. private final L2Npc _controller;
  180. private int _counter;
  181. private int _despawnedSporesCount;
  182. private final int[] _indexCount =
  183. {
  184. 0,
  185. 0
  186. };
  187. private int _challengeState;
  188. private int _winIndex;
  189. private final Map<Integer, Boolean> _activeRooms = new FastMap<>();
  190. private final Map<Integer, List<L2Npc>> _spawns = new FastMap<>();
  191. private final FastList<L2Npc> _sporeSpawn = new FastList<L2Npc>().shared();
  192. static
  193. {
  194. // Format: entrance_door, exit_door
  195. DOORS.put(18494, new int[]
  196. {
  197. 18250001,
  198. 18250002
  199. });
  200. DOORS.put(18495, new int[]
  201. {
  202. 18250003,
  203. 18250004
  204. });
  205. DOORS.put(18496, new int[]
  206. {
  207. 18250005,
  208. 18250006
  209. });
  210. DOORS.put(18497, new int[]
  211. {
  212. 18250007,
  213. 18250008
  214. });
  215. DOORS.put(18498, new int[]
  216. {
  217. 18250009,
  218. 18250010
  219. });
  220. DOORS.put(18499, new int[]
  221. {
  222. 18250011,
  223. 18250101
  224. });
  225. DOORS.put(18500, new int[]
  226. {
  227. 18250013,
  228. 18250014
  229. });
  230. DOORS.put(18501, new int[]
  231. {
  232. 18250015,
  233. 18250102
  234. });
  235. DOORS.put(18502, new int[]
  236. {
  237. 18250017,
  238. 18250018
  239. });
  240. DOORS.put(18503, new int[]
  241. {
  242. 18250019,
  243. 18250103
  244. });
  245. DOORS.put(18504, new int[]
  246. {
  247. 18250021,
  248. 18250022
  249. });
  250. DOORS.put(18505, new int[]
  251. {
  252. 18250023,
  253. 18250024
  254. });
  255. ZONES.put(18494, 200020);
  256. ZONES.put(18495, 200021);
  257. ZONES.put(18496, 200022);
  258. ZONES.put(18497, 200023);
  259. ZONES.put(18498, 200024);
  260. ZONES.put(18499, 200025);
  261. ZONES.put(18500, 200026);
  262. ZONES.put(18501, 200027);
  263. ZONES.put(18502, 200028);
  264. ZONES.put(18503, 200029);
  265. ZONES.put(18504, 200030);
  266. ZONES.put(18505, 200031);
  267. SPAWNS.put(18494, new int[][]
  268. {
  269. {
  270. 22393,
  271. -46371,
  272. 246400,
  273. -9120,
  274. 0
  275. },
  276. {
  277. 22394,
  278. -46435,
  279. 245830,
  280. -9120,
  281. 0
  282. },
  283. {
  284. 22394,
  285. -46536,
  286. 246275,
  287. -9120,
  288. 0
  289. },
  290. {
  291. 22393,
  292. -46239,
  293. 245996,
  294. -9120,
  295. 0
  296. },
  297. {
  298. 22394,
  299. -46229,
  300. 246347,
  301. -9120,
  302. 0
  303. },
  304. {
  305. 22394,
  306. -46019,
  307. 246198,
  308. -9120,
  309. 0
  310. }
  311. });
  312. SPAWNS.put(18495, new int[][]
  313. {
  314. {
  315. 22439,
  316. -48146,
  317. 249597,
  318. -9124,
  319. -16280
  320. },
  321. {
  322. 22439,
  323. -48144,
  324. 248711,
  325. -9124,
  326. 16368
  327. },
  328. {
  329. 22439,
  330. -48704,
  331. 249597,
  332. -9104,
  333. -16380
  334. },
  335. {
  336. 22439,
  337. -49219,
  338. 249596,
  339. -9104,
  340. -16400
  341. },
  342. {
  343. 22439,
  344. -49715,
  345. 249601,
  346. -9104,
  347. -16360
  348. },
  349. {
  350. 22439,
  351. -49714,
  352. 248696,
  353. -9104,
  354. 15932
  355. },
  356. {
  357. 22439,
  358. -49225,
  359. 248710,
  360. -9104,
  361. 16512
  362. },
  363. {
  364. 22439,
  365. -48705,
  366. 248708,
  367. -9104,
  368. 16576
  369. }
  370. });
  371. SPAWNS.put(18496, new int[][]
  372. {
  373. {
  374. 22441,
  375. -51176,
  376. 246055,
  377. -9984,
  378. 0
  379. },
  380. {
  381. 22441,
  382. -51699,
  383. 246190,
  384. -9984,
  385. 0
  386. },
  387. {
  388. 22442,
  389. -52060,
  390. 245956,
  391. -9984,
  392. 0
  393. },
  394. {
  395. 22442,
  396. -51565,
  397. 246433,
  398. -9984,
  399. 0
  400. }
  401. });
  402. SPAWNS.put(18497, new int[][]
  403. {
  404. {
  405. 22440,
  406. -49754,
  407. 243866,
  408. -9968,
  409. -16328
  410. },
  411. {
  412. 22440,
  413. -49754,
  414. 242940,
  415. -9968,
  416. 16336
  417. },
  418. {
  419. 22440,
  420. -48733,
  421. 243858,
  422. -9968,
  423. -16208
  424. },
  425. {
  426. 22440,
  427. -48745,
  428. 242936,
  429. -9968,
  430. 16320
  431. },
  432. {
  433. 22440,
  434. -49264,
  435. 242946,
  436. -9968,
  437. 16312
  438. },
  439. {
  440. 22440,
  441. -49268,
  442. 243869,
  443. -9968,
  444. -16448
  445. },
  446. {
  447. 22440,
  448. -48186,
  449. 242934,
  450. -9968,
  451. 16576
  452. },
  453. {
  454. 22440,
  455. -48185,
  456. 243855,
  457. -9968,
  458. -16448
  459. }
  460. });
  461. SPAWNS.put(18498, new int[][]
  462. {
  463. {
  464. 22411,
  465. -46355,
  466. 246375,
  467. -9984,
  468. 0
  469. },
  470. {
  471. 22411,
  472. -46167,
  473. 246160,
  474. -9984,
  475. 0
  476. },
  477. {
  478. 22393,
  479. -45952,
  480. 245748,
  481. -9984,
  482. 0
  483. },
  484. {
  485. 22394,
  486. -46428,
  487. 246254,
  488. -9984,
  489. 0
  490. },
  491. {
  492. 22393,
  493. -46490,
  494. 245871,
  495. -9984,
  496. 0
  497. },
  498. {
  499. 22394,
  500. -45877,
  501. 246309,
  502. -9984,
  503. 0
  504. }
  505. });
  506. SPAWNS.put(18499, new int[][]
  507. {
  508. {
  509. 22395,
  510. -48730,
  511. 248067,
  512. -9984,
  513. 0
  514. },
  515. {
  516. 22395,
  517. -49112,
  518. 248250,
  519. -9984,
  520. 0
  521. }
  522. });
  523. SPAWNS.put(18500, new int[][]
  524. {
  525. {
  526. 22393,
  527. -51954,
  528. 246475,
  529. -10848,
  530. 0
  531. },
  532. {
  533. 22394,
  534. -51421,
  535. 246512,
  536. -10848,
  537. 0
  538. },
  539. {
  540. 22394,
  541. -51404,
  542. 245951,
  543. -10848,
  544. 0
  545. },
  546. {
  547. 22393,
  548. -51913,
  549. 246206,
  550. -10848,
  551. 0
  552. },
  553. {
  554. 22394,
  555. -51663,
  556. 245979,
  557. -10848,
  558. 0
  559. },
  560. {
  561. 22394,
  562. -51969,
  563. 245809,
  564. -10848,
  565. 0
  566. },
  567. {
  568. 22412,
  569. -51259,
  570. 246357,
  571. -10848,
  572. 0
  573. }
  574. });
  575. SPAWNS.put(18501, new int[][]
  576. {
  577. {
  578. 22395,
  579. -48856,
  580. 243949,
  581. -10848,
  582. 0
  583. },
  584. {
  585. 22395,
  586. -49144,
  587. 244190,
  588. -10848,
  589. 0
  590. }
  591. });
  592. SPAWNS.put(18502, new int[][]
  593. {
  594. {
  595. 22441,
  596. -46471,
  597. 246135,
  598. -11704,
  599. 0
  600. },
  601. {
  602. 22441,
  603. -46449,
  604. 245997,
  605. -11704,
  606. 0
  607. },
  608. {
  609. 22441,
  610. -46235,
  611. 246187,
  612. -11704,
  613. 0
  614. },
  615. {
  616. 22441,
  617. -46513,
  618. 246326,
  619. -11704,
  620. 0
  621. },
  622. {
  623. 22441,
  624. -45889,
  625. 246313,
  626. -11704,
  627. 0
  628. }
  629. });
  630. SPAWNS.put(18503, new int[][]
  631. {
  632. {
  633. 22395,
  634. -49067,
  635. 248050,
  636. -11712,
  637. 0
  638. },
  639. {
  640. 22395,
  641. -48957,
  642. 248223,
  643. -11712,
  644. 0
  645. }
  646. });
  647. SPAWNS.put(18504, new int[][]
  648. {
  649. {
  650. 22413,
  651. -51748,
  652. 246138,
  653. -12568,
  654. 0
  655. },
  656. {
  657. 22413,
  658. -51279,
  659. 246200,
  660. -12568,
  661. 0
  662. },
  663. {
  664. 22413,
  665. -51787,
  666. 246594,
  667. -12568,
  668. 0
  669. },
  670. {
  671. 22413,
  672. -51892,
  673. 246544,
  674. -12568,
  675. 0
  676. },
  677. {
  678. 22413,
  679. -51500,
  680. 245781,
  681. -12568,
  682. 0
  683. },
  684. {
  685. 22413,
  686. -51941,
  687. 246045,
  688. -12568,
  689. 0
  690. }
  691. });
  692. SPAWNS.put(18505, new int[][]
  693. {
  694. {
  695. 18490,
  696. -48238,
  697. 243347,
  698. -13376,
  699. 0
  700. },
  701. {
  702. 18490,
  703. -48462,
  704. 244022,
  705. -13376,
  706. 0
  707. },
  708. {
  709. 18490,
  710. -48050,
  711. 244045,
  712. -13376,
  713. 0
  714. },
  715. {
  716. 18490,
  717. -48229,
  718. 243823,
  719. -13376,
  720. 0
  721. },
  722. {
  723. 18490,
  724. -47871,
  725. 243208,
  726. -13376,
  727. 0
  728. },
  729. {
  730. 18490,
  731. -48255,
  732. 243528,
  733. -13376,
  734. 0
  735. },
  736. {
  737. 18490,
  738. -48461,
  739. 243780,
  740. -13376,
  741. 0
  742. },
  743. {
  744. 18490,
  745. -47983,
  746. 243197,
  747. -13376,
  748. 0
  749. },
  750. {
  751. 18490,
  752. -47841,
  753. 243819,
  754. -13376,
  755. 0
  756. },
  757. {
  758. 18490,
  759. -48646,
  760. 243764,
  761. -13376,
  762. 0
  763. },
  764. {
  765. 18490,
  766. -47806,
  767. 243850,
  768. -13376,
  769. 0
  770. },
  771. {
  772. 18490,
  773. -48456,
  774. 243447,
  775. -13376,
  776. 0
  777. }
  778. });
  779. }
  780. public TowerOfNaia(int questId, String name, String descr)
  781. {
  782. super(questId, name, descr);
  783. addFirstTalkId(CONTROLLER);
  784. addStartNpc(CONTROLLER);
  785. addStartNpc(DWARVEN_GHOST);
  786. addTalkId(CONTROLLER);
  787. addTalkId(DWARVEN_GHOST);
  788. addAttackId(LOCK);
  789. addKillId(LOCK);
  790. addKillId(MUTATED_ELPY);
  791. addSpawnId(MUTATED_ELPY);
  792. addKillId(SPORE_BASIC);
  793. addSpawnId(SPORE_BASIC);
  794. for (int npcId = SPORE_FIRE; npcId <= SPORE_EARTH; npcId++)
  795. {
  796. addKillId(npcId);
  797. addSpawnId(npcId);
  798. }
  799. for (int npcId = ROOM_MANAGER_FIRST; npcId <= ROOM_MANAGER_LAST; npcId++)
  800. {
  801. addFirstTalkId(npcId);
  802. addTalkId(npcId);
  803. addStartNpc(npcId);
  804. initRoom(npcId);
  805. }
  806. for (int npcId : TOWER_MONSTERS)
  807. {
  808. addKillId(npcId);
  809. }
  810. _lock = (L2MonsterInstance) addSpawn(LOCK, 16409, 244438, 11620, -1048, false, 0, false);
  811. _controller = addSpawn(CONTROLLER, 16608, 244420, 11620, 31264, false, 0, false);
  812. _counter = 90;
  813. _despawnedSporesCount = 0;
  814. _challengeState = 0;
  815. _winIndex = -1;
  816. initSporeChallenge();
  817. spawnElpy();
  818. }
  819. @Override
  820. public final String onFirstTalk(L2Npc npc, L2PcInstance player)
  821. {
  822. int npcId = npc.getId();
  823. if (npcId == CONTROLLER)
  824. {
  825. if (_lock == null)
  826. {
  827. return "18492-02.htm";
  828. }
  829. return "18492-01.htm";
  830. }
  831. else if ((npcId >= ROOM_MANAGER_FIRST) && (npcId <= ROOM_MANAGER_LAST))
  832. {
  833. if (_activeRooms.containsKey(npcId) && !_activeRooms.get(npcId))
  834. {
  835. if (player.getParty() == null)
  836. {
  837. player.sendPacket(SystemMessageId.CAN_OPERATE_MACHINE_WHEN_IN_PARTY);
  838. return null;
  839. }
  840. return "manager.htm";
  841. }
  842. }
  843. return null;
  844. }
  845. @Override
  846. public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
  847. {
  848. String htmltext = event;
  849. // Timer. Spawns Naia Lock
  850. if (event.equalsIgnoreCase("spawn_lock"))
  851. {
  852. htmltext = null;
  853. _lock = (L2MonsterInstance) addSpawn(LOCK, 16409, 244438, 11620, -1048, false, 0, false);
  854. _counter = 90;
  855. }
  856. // Timer. Depending of _challengeState despans all spawned spores, or spores, reached assembly point
  857. else if (event.equalsIgnoreCase("despawn_total"))
  858. {
  859. // Spores is not attacked too long - despawn them all, reinit values
  860. if (_challengeState == STATE_SPORE_IDLE_TOO_LONG)
  861. {
  862. for (L2Npc spore : _sporeSpawn)
  863. {
  864. if ((spore != null) && !spore.isDead())
  865. {
  866. spore.deleteMe();
  867. }
  868. }
  869. _sporeSpawn.clear();
  870. initSporeChallenge();
  871. }
  872. // Spores are moving to assembly point. Despawn all reached, check for reached spores count.
  873. else if ((_challengeState == STATE_SPORE_CHALLENGE_SUCCESSFULL) && (_winIndex >= 0))
  874. {
  875. // Requirements are met, despawn all spores, spawn Epidos
  876. if ((_despawnedSporesCount >= 10) || _sporeSpawn.isEmpty())
  877. {
  878. if (!_sporeSpawn.isEmpty())
  879. {
  880. for (L2Npc spore : _sporeSpawn)
  881. {
  882. if ((spore != null) && !spore.isDead())
  883. {
  884. spore.deleteMe();
  885. }
  886. }
  887. }
  888. _sporeSpawn.clear();
  889. _despawnedSporesCount = 0;
  890. int[] coords = SPORES_MERGE_POSITION[_winIndex];
  891. addSpawn(EPIDOSES[_winIndex], coords[0], coords[1], coords[2], 0, false, 0, false);
  892. initSporeChallenge();
  893. }
  894. // Requirements aren't met, despawn reached spores
  895. else
  896. {
  897. Iterator<L2Npc> it = _sporeSpawn.iterator();
  898. while (it.hasNext())
  899. {
  900. L2Npc spore = it.next();
  901. if ((spore != null) && !spore.isDead() && (spore.getX() == spore.getSpawn().getX()) && (spore.getY() == spore.getSpawn().getY()))
  902. {
  903. spore.deleteMe();
  904. it.remove();
  905. _despawnedSporesCount++;
  906. }
  907. }
  908. startQuestTimer("despawn_total", 3000, null, null);
  909. }
  910. }
  911. }
  912. if (npc == null)
  913. {
  914. return null;
  915. }
  916. int npcId = npc.getId();
  917. if (event.equalsIgnoreCase("despawn_spore") && !npc.isDead() && (_challengeState == STATE_SPORE_CHALLENGE_IN_PROGRESS))
  918. {
  919. htmltext = null;
  920. _sporeSpawn.remove(npc);
  921. npc.deleteMe();
  922. if (npcId == SPORE_BASIC)
  923. {
  924. spawnRandomSpore();
  925. spawnRandomSpore();
  926. }
  927. else if ((npcId >= SPORE_FIRE) && (npcId <= SPORE_EARTH))
  928. {
  929. _despawnedSporesCount++;
  930. /*
  931. * if (_despawnedSporesCount % 20 == 0) { Announcements.getInstance().announceToAll("Despawned " + Integer.toString(_despawnedSporesCount) + " creatures"); }
  932. */
  933. if (_despawnedSporesCount < SELF_DESPAWN_LIMIT)
  934. {
  935. spawnOppositeSpore(npcId);
  936. }
  937. else
  938. {
  939. _challengeState = STATE_SPORE_IDLE_TOO_LONG;
  940. startQuestTimer("despawn_total", 60000, null, null);
  941. }
  942. }
  943. }
  944. else if (event.equalsIgnoreCase("18492-05.htm"))
  945. {
  946. if ((_lock == null) || (_lock.getCurrentHp() > (_lock.getMaxHp() / 10)))
  947. {
  948. htmltext = null;
  949. if (_lock != null)
  950. {
  951. _lock.deleteMe();
  952. _lock = null;
  953. }
  954. cancelQuestTimers("spawn_lock");
  955. startQuestTimer("spawn_lock", 300000, null, null);
  956. npc.setTarget(player);
  957. npc.doCast(SkillData.getInstance().getSkill(5527, 1));
  958. }
  959. }
  960. else if (event.equalsIgnoreCase("teleport") && (_lock != null))
  961. {
  962. htmltext = null;
  963. L2Party party = player.getParty();
  964. if (party != null)
  965. {
  966. if (Util.checkIfInRange(3000, party.getLeader(), npc, true))
  967. {
  968. for (L2PcInstance partyMember : party.getMembers())
  969. {
  970. if (Util.checkIfInRange(2000, partyMember, npc, true))
  971. {
  972. partyMember.teleToLocation(-47271, 246098, -9120, true);
  973. }
  974. }
  975. _lock.deleteMe();
  976. _lock = null;
  977. cancelQuestTimers("spawn_lock");
  978. startQuestTimer("spawn_lock", 1200000, null, null);
  979. }
  980. else
  981. {
  982. npc.setTarget(player);
  983. npc.doCast(SkillData.getInstance().getSkill(5527, 1));
  984. }
  985. }
  986. else
  987. {
  988. player.teleToLocation(-47271, 246098, -9120);
  989. _lock.deleteMe();
  990. _lock = null;
  991. cancelQuestTimers("spawn_lock");
  992. startQuestTimer("spawn_lock", 1200000, null, null);
  993. }
  994. }
  995. else if (event.equalsIgnoreCase("go") && _activeRooms.containsKey(npcId) && !_activeRooms.get(npcId))
  996. {
  997. htmltext = null;
  998. L2Party party = player.getParty();
  999. if (party != null)
  1000. {
  1001. removeForeigners(npcId, party);
  1002. startRoom(npcId);
  1003. ThreadPoolManager.getInstance().scheduleGeneral(new StopRoomTask(npcId), 300000);
  1004. }
  1005. else
  1006. {
  1007. player.sendPacket(SystemMessageId.CAN_OPERATE_MACHINE_WHEN_IN_PARTY);
  1008. }
  1009. }
  1010. return htmltext;
  1011. }
  1012. @Override
  1013. public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
  1014. {
  1015. if ((_lock != null) && (npc.getObjectId() == _lock.getObjectId()))
  1016. {
  1017. int remaindedHpPercent = (int) ((npc.getCurrentHp() * 100) / npc.getMaxHp());
  1018. if ((remaindedHpPercent <= _counter) && (_controller != null))
  1019. {
  1020. if (_counter == 50)
  1021. {
  1022. MinionList.spawnMinion(_lock, 18493);
  1023. }
  1024. else if (_counter == 10)
  1025. {
  1026. MinionList.spawnMinion(_lock, 18493);
  1027. MinionList.spawnMinion(_lock, 18493);
  1028. }
  1029. _controller.broadcastPacket(new NpcSay(_controller.getObjectId(), Say2.NPC_ALL, _controller.getId(), NpcStringId.EMERGENCY_EMERGENCY_THE_OUTER_WALL_IS_WEAKENING_RAPIDLY));
  1030. _counter -= 10;
  1031. }
  1032. }
  1033. return super.onAttack(npc, attacker, damage, isSummon, skill);
  1034. }
  1035. @Override
  1036. public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
  1037. {
  1038. int npcId = npc.getId();
  1039. if (npcId == LOCK)
  1040. {
  1041. _lock = null;
  1042. cancelQuestTimers("spawn_lock");
  1043. startQuestTimer("spawn_lock", 300000, null, null);
  1044. }
  1045. else if (Arrays.binarySearch(TOWER_MONSTERS, npcId) >= 0)
  1046. {
  1047. int managerId = 0;
  1048. for (L2ZoneType zone : ZoneManager.getInstance().getZones(npc.getX(), npc.getY(), npc.getZ()))
  1049. {
  1050. if (ZONES.containsValue(zone.getId()))
  1051. {
  1052. for (int i : ZONES.keySet())
  1053. {
  1054. if (ZONES.get(i) == zone.getId())
  1055. {
  1056. managerId = i;
  1057. break;
  1058. }
  1059. }
  1060. }
  1061. }
  1062. if ((managerId > 0) && _spawns.containsKey(managerId))
  1063. {
  1064. List<L2Npc> spawned = _spawns.get(managerId);
  1065. spawned.remove(npc);
  1066. if (spawned.isEmpty() && DOORS.containsKey(managerId))
  1067. {
  1068. int[] doorList = DOORS.get(managerId);
  1069. DoorTable.getInstance().getDoor(doorList[1]).openMe();
  1070. _spawns.remove(managerId);
  1071. }
  1072. }
  1073. }
  1074. else if (npcId == MUTATED_ELPY)
  1075. {
  1076. _challengeState = STATE_SPORE_CHALLENGE_IN_PROGRESS;
  1077. markElpyRespawn();
  1078. DoorTable.getInstance().getDoor(18250025).closeMe();
  1079. ZoneManager.getInstance().getZoneById(200100).setEnabled(true);
  1080. for (int i = 0; i < 10; i++)
  1081. {
  1082. addSpawn(SPORE_BASIC, -45474, 247450, -13994, 49152, false, 0, false);
  1083. }
  1084. }
  1085. else if ((npcId == SPORE_BASIC) && (_challengeState == STATE_SPORE_CHALLENGE_IN_PROGRESS))
  1086. {
  1087. _sporeSpawn.remove(npc);
  1088. spawnRandomSpore();
  1089. spawnRandomSpore();
  1090. }
  1091. else if ((npcId >= SPORE_FIRE) && (npcId <= SPORE_EARTH) && ((_challengeState == STATE_SPORE_CHALLENGE_IN_PROGRESS) || (_challengeState == STATE_SPORE_CHALLENGE_SUCCESSFULL)))
  1092. {
  1093. _sporeSpawn.remove(npc);
  1094. if (_challengeState == STATE_SPORE_CHALLENGE_IN_PROGRESS)
  1095. {
  1096. _despawnedSporesCount--;
  1097. int sporeGroup = getSporeGroup(npcId);
  1098. if (sporeGroup >= 0)
  1099. {
  1100. if ((npcId == SPORE_FIRE) || (npcId == SPORE_WIND))
  1101. {
  1102. _indexCount[sporeGroup] += 2;
  1103. }
  1104. else
  1105. {
  1106. _indexCount[sporeGroup] -= 2;
  1107. }
  1108. if (_indexCount[Math.abs(sporeGroup - 1)] > 0)
  1109. {
  1110. _indexCount[Math.abs(sporeGroup - 1)]--;
  1111. }
  1112. else if (_indexCount[Math.abs(sporeGroup - 1)] < 0)
  1113. {
  1114. _indexCount[Math.abs(sporeGroup - 1)]++;
  1115. }
  1116. if ((Math.abs(_indexCount[sporeGroup]) < ELEMENT_INDEX_LIMIT) && (Math.abs(_indexCount[sporeGroup]) > 0) && ((_indexCount[sporeGroup] % 20) == 0) && (getRandom(100) < 50))
  1117. {
  1118. String el = ELEMENTS_NAME[Arrays.binarySearch(ELEMENTS, npcId)];
  1119. for (L2Npc spore : _sporeSpawn)
  1120. {
  1121. if ((spore != null) && !spore.isDead() && (spore.getId() == npcId))
  1122. {
  1123. NpcSay ns = new NpcSay(spore.getObjectId(), Say2.NPC_ALL, spore.getId(), SPORES_NPCSTRING_ID[getRandom(4)]);
  1124. ns.addStringParameter(el);
  1125. spore.broadcastPacket(ns);
  1126. }
  1127. }
  1128. }
  1129. if (Math.abs(_indexCount[sporeGroup]) < ELEMENT_INDEX_LIMIT)
  1130. {
  1131. if ((((_indexCount[sporeGroup] > 0) && ((npcId == SPORE_FIRE) || (npcId == SPORE_WIND))) || ((_indexCount[sporeGroup] <= 0) && ((npcId == SPORE_WATER) || (npcId == SPORE_EARTH)))) && (getRandom(1000) > 200))
  1132. {
  1133. spawnOppositeSpore(npcId);
  1134. }
  1135. else
  1136. {
  1137. spawnRandomSpore();
  1138. }
  1139. }
  1140. else
  1141. // index value was reached
  1142. {
  1143. _challengeState = STATE_SPORE_CHALLENGE_SUCCESSFULL;
  1144. _despawnedSporesCount = 0;
  1145. _winIndex = Arrays.binarySearch(ELEMENTS, npcId);
  1146. int[] coord = SPORES_MERGE_POSITION[_winIndex];
  1147. for (L2Npc spore : _sporeSpawn)
  1148. {
  1149. if ((spore != null) && !spore.isDead())
  1150. {
  1151. moveTo(spore, coord);
  1152. }
  1153. }
  1154. startQuestTimer("despawn_total", 3000, null, null);
  1155. }
  1156. }
  1157. }
  1158. }
  1159. return super.onKill(npc, killer, isSummon);
  1160. }
  1161. @Override
  1162. public final String onSpawn(L2Npc npc)
  1163. {
  1164. int npcId = npc.getId();
  1165. if ((npcId == MUTATED_ELPY) && !npc.isTeleporting())
  1166. {
  1167. DoorTable.getInstance().getDoor(18250025).openMe();
  1168. ZoneManager.getInstance().getZoneById(200100).setEnabled(false);
  1169. ZoneManager.getInstance().getZoneById(200101).setEnabled(true);
  1170. ZoneManager.getInstance().getZoneById(200101).setEnabled(false);
  1171. }
  1172. else if (((npcId == SPORE_BASIC) || ((npcId >= SPORE_FIRE) && (npcId <= SPORE_EARTH))) && (_challengeState == STATE_SPORE_CHALLENGE_IN_PROGRESS))
  1173. {
  1174. _sporeSpawn.add(npc);
  1175. npc.setIsRunning(false);
  1176. int[] coord = SPORES_MOVE_POINTS[getRandom(SPORES_MOVE_POINTS.length)];
  1177. npc.getSpawn().setX(coord[0]);
  1178. npc.getSpawn().setY(coord[1]);
  1179. npc.getSpawn().setZ(coord[2]);
  1180. npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(coord[0], coord[1], coord[2], 0));
  1181. startQuestTimer("despawn_spore", 60000, npc, null);
  1182. }
  1183. return super.onSpawn(npc);
  1184. }
  1185. private int getSporeGroup(int sporeId)
  1186. {
  1187. int ret;
  1188. switch (sporeId)
  1189. {
  1190. case SPORE_FIRE:
  1191. case SPORE_WATER:
  1192. ret = 0;
  1193. break;
  1194. case SPORE_WIND:
  1195. case SPORE_EARTH:
  1196. ret = 1;
  1197. break;
  1198. default:
  1199. ret = -1;
  1200. }
  1201. return ret;
  1202. }
  1203. protected void initRoom(int managerId)
  1204. {
  1205. removeAllPlayers(managerId);
  1206. _activeRooms.put(managerId, false);
  1207. if (DOORS.containsKey(managerId))
  1208. {
  1209. int[] doorList = DOORS.get(managerId);
  1210. DoorTable.getInstance().getDoor(doorList[0]).openMe();
  1211. DoorTable.getInstance().getDoor(doorList[1]).closeMe();
  1212. }
  1213. if (_spawns.containsKey(managerId) && (_spawns.get(managerId) != null))
  1214. {
  1215. for (L2Npc npc : _spawns.get(managerId))
  1216. {
  1217. if ((npc != null) && !npc.isDead())
  1218. {
  1219. npc.deleteMe();
  1220. }
  1221. }
  1222. _spawns.get(managerId).clear();
  1223. _spawns.remove(managerId);
  1224. }
  1225. }
  1226. private void initSporeChallenge()
  1227. {
  1228. _despawnedSporesCount = 0;
  1229. _challengeState = 0;
  1230. _winIndex = -1;
  1231. _indexCount[0] = 0;
  1232. _indexCount[1] = 0;
  1233. ZoneManager.getInstance().getZoneById(200100).setEnabled(false);
  1234. ZoneManager.getInstance().getZoneById(200101).setEnabled(false);
  1235. ZoneManager.getInstance().getZoneById(200101).setEnabled(true);
  1236. }
  1237. private void markElpyRespawn()
  1238. {
  1239. final long respawnTime = (getRandom(43200, 216000) * 1000) + System.currentTimeMillis();
  1240. GlobalVariablesManager.getInstance().set("elpy_respawn_time", respawnTime);
  1241. }
  1242. private int moveTo(L2Npc npc, int[] coords)
  1243. {
  1244. int time = 0;
  1245. if (npc != null)
  1246. {
  1247. double distance = npc.calculateDistance(coords[0], coords[1], coords[2], true, false);
  1248. int heading = Util.calculateHeadingFrom(npc.getX(), npc.getY(), coords[0], coords[1]);
  1249. time = (int) ((distance / npc.getWalkSpeed()) * 1000);
  1250. npc.setIsRunning(false);
  1251. npc.disableCoreAI(true);
  1252. npc.setIsNoRndWalk(true);
  1253. npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(coords[0], coords[1], coords[2], heading));
  1254. npc.getSpawn().setX(coords[0]);
  1255. npc.getSpawn().setY(coords[1]);
  1256. npc.getSpawn().setZ(coords[2]);
  1257. }
  1258. return time == 0 ? 100 : time;
  1259. }
  1260. private void spawnElpy()
  1261. {
  1262. final long respawnTime = GlobalVariablesManager.getInstance().getLong("elpy_respawn_time", 0);
  1263. if (respawnTime <= System.currentTimeMillis())
  1264. {
  1265. addSpawn(MUTATED_ELPY, -45474, 247450, -13994, 49152, false, 0, false);
  1266. }
  1267. else
  1268. {
  1269. ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
  1270. {
  1271. @Override
  1272. public void run()
  1273. {
  1274. addSpawn(MUTATED_ELPY, -45474, 247450, -13994, 49152, false, 0, false);
  1275. }
  1276. }, respawnTime - System.currentTimeMillis());
  1277. }
  1278. }
  1279. private L2Npc spawnRandomSpore()
  1280. {
  1281. return addSpawn(getRandom(SPORE_FIRE, SPORE_EARTH), -45474, 247450, -13994, 49152, false, 0, false);
  1282. }
  1283. private L2Npc spawnOppositeSpore(int srcSporeId)
  1284. {
  1285. int idx = Arrays.binarySearch(ELEMENTS, srcSporeId);
  1286. return idx >= 0 ? addSpawn(OPPOSITE_ELEMENTS[idx], -45474, 247450, -13994, 49152, false, 0, false) : null;
  1287. }
  1288. private void startRoom(int managerId)
  1289. {
  1290. _activeRooms.put(managerId, true);
  1291. if (DOORS.containsKey(managerId))
  1292. {
  1293. int[] doorList = DOORS.get(managerId);
  1294. DoorTable.getInstance().getDoor(doorList[0]).closeMe();
  1295. }
  1296. if (SPAWNS.containsKey(managerId))
  1297. {
  1298. int[][] spawnList = SPAWNS.get(managerId);
  1299. List<L2Npc> spawned = new FastList<>();
  1300. for (int[] spawn : spawnList)
  1301. {
  1302. L2Npc spawnedNpc = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false);
  1303. spawned.add(spawnedNpc);
  1304. }
  1305. if (!spawned.isEmpty())
  1306. {
  1307. _spawns.put(managerId, spawned);
  1308. }
  1309. }
  1310. }
  1311. private void removeForeigners(int managerId, L2Party party)
  1312. {
  1313. if ((party != null) && ZONES.containsKey(managerId) && (ZoneManager.getInstance().getZoneById(ZONES.get(managerId)) != null))
  1314. {
  1315. L2ZoneType zone = ZoneManager.getInstance().getZoneById(ZONES.get(managerId));
  1316. for (L2PcInstance player : zone.getPlayersInside())
  1317. {
  1318. if (player != null)
  1319. {
  1320. L2Party charParty = player.getParty();
  1321. if ((charParty == null) || (charParty.getLeaderObjectId() != party.getLeaderObjectId()))
  1322. {
  1323. player.teleToLocation(16110, 243841, 11616);
  1324. }
  1325. }
  1326. }
  1327. }
  1328. }
  1329. private void removeAllPlayers(int managerId)
  1330. {
  1331. if (ZONES.containsKey(managerId) && (ZoneManager.getInstance().getZoneById(ZONES.get(managerId)) != null))
  1332. {
  1333. L2ZoneType zone = ZoneManager.getInstance().getZoneById(ZONES.get(managerId));
  1334. for (L2PcInstance player : zone.getPlayersInside())
  1335. {
  1336. if (player != null)
  1337. {
  1338. player.teleToLocation(16110, 243841, 11616);
  1339. }
  1340. }
  1341. }
  1342. }
  1343. private class StopRoomTask implements Runnable
  1344. {
  1345. private final int _managerId;
  1346. public StopRoomTask(int managerId)
  1347. {
  1348. _managerId = managerId;
  1349. }
  1350. @Override
  1351. public void run()
  1352. {
  1353. initRoom(_managerId);
  1354. }
  1355. }
  1356. public static void main(String[] args)
  1357. {
  1358. new TowerOfNaia(-1, "TowerOfNaia", "hellbound");
  1359. }
  1360. }