Q00421_LittleWingsBigAdventure.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /*
  2. * Copyright (C) 2004-2015 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 quests.Q00421_LittleWingsBigAdventure;
  20. import java.util.HashMap;
  21. import java.util.Map;
  22. import com.l2jserver.gameserver.ai.CtrlIntention;
  23. import com.l2jserver.gameserver.enums.QuestSound;
  24. import com.l2jserver.gameserver.model.actor.L2Npc;
  25. import com.l2jserver.gameserver.model.actor.L2Summon;
  26. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  27. import com.l2jserver.gameserver.model.holders.SkillHolder;
  28. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  29. import com.l2jserver.gameserver.model.quest.Quest;
  30. import com.l2jserver.gameserver.model.quest.QuestState;
  31. import com.l2jserver.gameserver.model.quest.State;
  32. import com.l2jserver.gameserver.network.NpcStringId;
  33. import com.l2jserver.gameserver.network.clientpackets.Say2;
  34. import com.l2jserver.gameserver.network.serverpackets.NpcSay;
  35. import com.l2jserver.gameserver.util.Util;
  36. /**
  37. * Little Wing's Big Adventure (421)
  38. * @author Pandragon, jurchiks
  39. */
  40. public final class Q00421_LittleWingsBigAdventure extends Quest
  41. {
  42. // NPCs
  43. private static final int CRONOS = 30610;
  44. private static final int MIMYU = 30747;
  45. // Items
  46. private static final int DRAGONFLUTE_OF_WIND = 3500;
  47. private static final int DRAGONFLUTE_OF_STAR = 3501;
  48. private static final int DRAGONFLUTE_OF_TWILIGHT = 3502;
  49. private static final int FAIRY_LEAF = 4325;
  50. // Monsters
  51. private static final int TREE_OF_WIND = 27185;
  52. private static final int TREE_OF_STAR = 27186;
  53. private static final int TREE_OF_TWILIGHT = 27187;
  54. private static final int TREE_OF_ABYSS = 27188;
  55. private static final int SOUL_OF_TREE_GUARDIAN = 27189;
  56. // Skills
  57. private static final SkillHolder CURSE_OF_MIMYU = new SkillHolder(4167, 1);
  58. private static final SkillHolder DRYAD_ROOT = new SkillHolder(1201, 33);
  59. private static final SkillHolder VICIOUS_POISON = new SkillHolder(4243, 1);
  60. // Rewards
  61. private static final int DRAGON_BUGLE_OF_WIND = 4422;
  62. private static final int DRAGON_BUGLE_OF_STAR = 4423;
  63. private static final int DRAGON_BUGLE_OF_TWILIGHT = 4424;
  64. // Misc
  65. private static final int MIN_PLAYER_LVL = 45;
  66. private static final int MIN_HACHLING_LVL = 55;
  67. private static final Map<Integer, NpcData> NPC_DATA = new HashMap<>();
  68. static
  69. {
  70. NPC_DATA.put(TREE_OF_WIND, new NpcData(NpcStringId.HEY_YOUVE_ALREADY_DRUNK_THE_ESSENCE_OF_WIND, 2, 1, 270));
  71. NPC_DATA.put(TREE_OF_STAR, new NpcData(NpcStringId.HEY_YOUVE_ALREADY_DRUNK_THE_ESSENCE_OF_A_STAR, 4, 2, 400));
  72. NPC_DATA.put(TREE_OF_TWILIGHT, new NpcData(NpcStringId.HEY_YOUVE_ALREADY_DRUNK_THE_ESSENCE_OF_DUSK, 8, 4, 150));
  73. NPC_DATA.put(TREE_OF_ABYSS, new NpcData(NpcStringId.HEY_YOUVE_ALREADY_DRUNK_THE_ESSENCE_OF_THE_ABYSS, 16, 8, 270));
  74. }
  75. public Q00421_LittleWingsBigAdventure()
  76. {
  77. super(421, Q00421_LittleWingsBigAdventure.class.getSimpleName(), "Little Wing's Big Adventure");
  78. addStartNpc(CRONOS);
  79. addTalkId(CRONOS, MIMYU);
  80. addAttackId(NPC_DATA.keySet());
  81. addKillId(NPC_DATA.keySet());
  82. registerQuestItems(FAIRY_LEAF);
  83. }
  84. @Override
  85. public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
  86. {
  87. if ("DESPAWN_GUARDIAN".equals(event))
  88. {
  89. if (npc != null)
  90. {
  91. npc.deleteMe();
  92. }
  93. return super.onAdvEvent(event, npc, player);
  94. }
  95. final QuestState qs = getQuestState(player, false);
  96. String htmltext = null;
  97. if (qs == null)
  98. {
  99. return htmltext;
  100. }
  101. switch (event)
  102. {
  103. case "30610-05.htm":
  104. {
  105. if (qs.isCreated())
  106. {
  107. if (getQuestItemsCount(player, DRAGONFLUTE_OF_WIND, DRAGONFLUTE_OF_STAR, DRAGONFLUTE_OF_TWILIGHT) == 1)
  108. {
  109. final L2ItemInstance flute = getFlute(player);
  110. if (flute.getEnchantLevel() < MIN_HACHLING_LVL)
  111. {
  112. htmltext = "30610-06.html";
  113. }
  114. else
  115. {
  116. qs.startQuest();
  117. qs.setMemoState(100);
  118. qs.set("fluteObjectId", flute.getObjectId());
  119. htmltext = event;
  120. }
  121. }
  122. else
  123. {
  124. htmltext = "30610-06.html";
  125. }
  126. }
  127. break;
  128. }
  129. case "30747-04.html":
  130. {
  131. final L2Summon summon = player.getSummon();
  132. if (summon == null)
  133. {
  134. htmltext = "30747-02.html";
  135. }
  136. else if (summon.getControlObjectId() != qs.getInt("fluteObjectId"))
  137. {
  138. htmltext = "30747-03.html";
  139. }
  140. else
  141. {
  142. htmltext = event;
  143. }
  144. break;
  145. }
  146. case "30747-05.html":
  147. {
  148. final L2Summon summon = player.getSummon();
  149. if (summon == null)
  150. {
  151. htmltext = "30747-06.html";
  152. }
  153. else if (summon.getControlObjectId() != qs.getInt("fluteObjectId"))
  154. {
  155. htmltext = "30747-06.html";
  156. }
  157. else
  158. {
  159. giveItems(player, FAIRY_LEAF, 4);
  160. qs.setCond(2, true);
  161. qs.setMemoState(0);
  162. htmltext = event;
  163. }
  164. break;
  165. }
  166. case "30747-07.html":
  167. case "30747-08.html":
  168. case "30747-09.html":
  169. case "30747-10.html":
  170. {
  171. htmltext = event;
  172. break;
  173. }
  174. }
  175. return htmltext;
  176. }
  177. @Override
  178. public String onTalk(L2Npc npc, L2PcInstance talker)
  179. {
  180. final QuestState qs = getQuestState(talker, true);
  181. String htmltext = getNoQuestMsg(talker);
  182. switch (npc.getId())
  183. {
  184. case CRONOS:
  185. {
  186. switch (qs.getState())
  187. {
  188. case State.CREATED:
  189. {
  190. final long fluteCount = getQuestItemsCount(talker, DRAGONFLUTE_OF_WIND, DRAGONFLUTE_OF_STAR, DRAGONFLUTE_OF_TWILIGHT);
  191. if (fluteCount == 0)
  192. {
  193. break; // this quest does not show up if no flute in inventory
  194. }
  195. if (talker.getLevel() < MIN_PLAYER_LVL)
  196. {
  197. htmltext = "30610-01.htm";
  198. }
  199. else if (fluteCount > 1)
  200. {
  201. htmltext = "30610-02.htm";
  202. }
  203. else if (getFlute(talker).getEnchantLevel() < MIN_HACHLING_LVL)
  204. {
  205. htmltext = "30610-03.html";
  206. }
  207. else
  208. {
  209. htmltext = "30610-04.htm";
  210. }
  211. break;
  212. }
  213. case State.STARTED:
  214. {
  215. htmltext = "30610-07.html";
  216. break;
  217. }
  218. case State.COMPLETED:
  219. {
  220. htmltext = getAlreadyCompletedMsg(talker);
  221. break;
  222. }
  223. }
  224. break;
  225. }
  226. case MIMYU:
  227. {
  228. switch (qs.getMemoState())
  229. {
  230. case 100:
  231. {
  232. qs.setMemoState(200);
  233. htmltext = "30747-01.html";
  234. break;
  235. }
  236. case 200:
  237. {
  238. final L2Summon summon = talker.getSummon();
  239. if (summon == null)
  240. {
  241. htmltext = "30747-02.html";
  242. }
  243. else if (summon.getControlObjectId() != qs.getInt("fluteObjectId"))
  244. {
  245. htmltext = "30747-03.html";
  246. }
  247. else
  248. {
  249. htmltext = "30747-04.html";
  250. }
  251. break;
  252. }
  253. case 0:
  254. {
  255. htmltext = "30747-07.html";
  256. break;
  257. }
  258. case 1:
  259. case 2:
  260. case 3:
  261. case 4:
  262. case 5:
  263. case 6:
  264. case 7:
  265. case 8:
  266. case 9:
  267. case 10:
  268. case 11:
  269. case 12:
  270. case 13:
  271. case 14:
  272. {
  273. if (hasQuestItems(talker, FAIRY_LEAF))
  274. {
  275. htmltext = "30747-11.html";
  276. }
  277. break;
  278. }
  279. case 15:
  280. {
  281. if (!hasQuestItems(talker, FAIRY_LEAF))
  282. {
  283. final L2Summon summon = talker.getSummon();
  284. if (summon == null)
  285. {
  286. htmltext = "30747-12.html";
  287. }
  288. else if (summon.getControlObjectId() == qs.getInt("fluteObjectId"))
  289. {
  290. qs.setMemoState(16);
  291. htmltext = "30747-13.html";
  292. }
  293. else
  294. {
  295. htmltext = "30747-14.html";
  296. }
  297. }
  298. break;
  299. }
  300. case 16:
  301. {
  302. if (!hasQuestItems(talker, FAIRY_LEAF))
  303. {
  304. if (talker.hasSummon())
  305. {
  306. htmltext = "30747-15.html";
  307. }
  308. else
  309. {
  310. final long fluteCount = getQuestItemsCount(talker, DRAGONFLUTE_OF_WIND, DRAGONFLUTE_OF_STAR, DRAGONFLUTE_OF_TWILIGHT);
  311. if (fluteCount > 1)
  312. {
  313. htmltext = "30747-17.html";
  314. }
  315. else if (fluteCount == 1)
  316. {
  317. final L2ItemInstance flute = getFlute(talker);
  318. if (flute.getObjectId() == qs.getInt("fluteObjectId"))
  319. {
  320. // TODO what if the hatchling has items in his inventory?
  321. // Should they be transfered to the strider or given to the player?
  322. switch (flute.getId())
  323. {
  324. case DRAGONFLUTE_OF_WIND:
  325. takeItems(talker, DRAGONFLUTE_OF_WIND, -1);
  326. giveItems(talker, DRAGON_BUGLE_OF_WIND, 1);
  327. break;
  328. case DRAGONFLUTE_OF_STAR:
  329. takeItems(talker, DRAGONFLUTE_OF_STAR, -1);
  330. giveItems(talker, DRAGON_BUGLE_OF_STAR, 1);
  331. break;
  332. case DRAGONFLUTE_OF_TWILIGHT:
  333. takeItems(talker, DRAGONFLUTE_OF_TWILIGHT, -1);
  334. giveItems(talker, DRAGON_BUGLE_OF_TWILIGHT, 1);
  335. break;
  336. }
  337. qs.exitQuest(true, true);
  338. htmltext = "30747-16.html";
  339. }
  340. else
  341. {
  342. npc.setTarget(talker);
  343. npc.doCast(CURSE_OF_MIMYU.getSkill());
  344. htmltext = "30747-18.html";
  345. }
  346. }
  347. }
  348. }
  349. break;
  350. }
  351. }
  352. break;
  353. }
  354. }
  355. return htmltext;
  356. }
  357. @Override
  358. public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
  359. {
  360. final QuestState qs = getQuestState(attacker, false);
  361. if ((qs != null) && qs.isCond(2))
  362. {
  363. if (isSummon)
  364. {
  365. final NpcData data = NPC_DATA.get(npc.getId());
  366. if ((qs.getMemoState() % data.memoStateMod) < data.memoStateValue)
  367. {
  368. if (attacker.getSummon().getControlObjectId() == qs.getInt("fluteObjectId"))
  369. {
  370. final int hits = qs.getInt("hits") + 1;
  371. qs.set("hits", hits);
  372. if (hits < data.minHits)
  373. {
  374. if ((npc.getId() == TREE_OF_ABYSS) && (getRandom(100) < 2))
  375. {
  376. npc.setTarget(attacker);
  377. npc.doCast(DRYAD_ROOT.getSkill());
  378. }
  379. }
  380. else if (getRandom(100) < 2)
  381. {
  382. if (hasQuestItems(attacker, FAIRY_LEAF))
  383. {
  384. npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.GIVE_ME_A_FAIRY_LEAF));
  385. takeItems(attacker, FAIRY_LEAF, 1);
  386. qs.setMemoState(qs.getMemoState() + data.memoStateValue);
  387. qs.unset("hits");
  388. playSound(attacker, QuestSound.ITEMSOUND_QUEST_MIDDLE);
  389. if (qs.getMemoState() == 15)
  390. {
  391. qs.setCond(3);
  392. }
  393. }
  394. }
  395. }
  396. }
  397. else
  398. {
  399. switch (getRandom(3))
  400. {
  401. case 0:
  402. npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.WHY_DO_YOU_BOTHER_ME_AGAIN));
  403. break;
  404. case 1:
  405. npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, data.message));
  406. break;
  407. case 2:
  408. npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.LEAVE_NOW_BEFORE_YOU_INCUR_THE_WRATH_OF_THE_GUARDIAN_GHOST));
  409. break;
  410. }
  411. }
  412. }
  413. else if (getRandom(100) < 30)
  414. {
  415. npc.setTarget(attacker);
  416. npc.doCast(VICIOUS_POISON.getSkill());
  417. }
  418. }
  419. else if ((npc.getCurrentHp() < (npc.getMaxHp() * 0.67)) && (getRandom(100) < 30))
  420. {
  421. npc.setTarget(attacker);
  422. npc.doCast(VICIOUS_POISON.getSkill());
  423. }
  424. return super.onAttack(npc, attacker, damage, isSummon);
  425. }
  426. @Override
  427. public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
  428. {
  429. if (Util.checkIfInRange(1500, killer, npc, true))
  430. {
  431. for (int i = 0; i < 20; i++)
  432. {
  433. L2Npc guardian = addSpawn(SOUL_OF_TREE_GUARDIAN, npc);
  434. startQuestTimer("DESPAWN_GUARDIAN", 300000, guardian, null);
  435. if (i == 0)
  436. {
  437. npc.setTarget(killer);
  438. npc.doCast(VICIOUS_POISON.getSkill());
  439. }
  440. npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, killer);
  441. }
  442. }
  443. return super.onKill(npc, killer, isSummon);
  444. }
  445. private static L2ItemInstance getFlute(L2PcInstance player)
  446. {
  447. final int fluteItemId;
  448. if (hasQuestItems(player, DRAGONFLUTE_OF_WIND))
  449. {
  450. fluteItemId = DRAGONFLUTE_OF_WIND;
  451. }
  452. else if (hasQuestItems(player, DRAGONFLUTE_OF_STAR))
  453. {
  454. fluteItemId = DRAGONFLUTE_OF_STAR;
  455. }
  456. else
  457. {
  458. fluteItemId = DRAGONFLUTE_OF_TWILIGHT;
  459. }
  460. return player.getInventory().getItemByItemId(fluteItemId);
  461. }
  462. private static final class NpcData
  463. {
  464. public final NpcStringId message;
  465. public final int memoStateMod;
  466. public final int memoStateValue;
  467. public final int minHits;
  468. public NpcData(NpcStringId message, int memoStateMod, int memoStateValue, int minHits)
  469. {
  470. this.message = message;
  471. this.memoStateMod = memoStateMod;
  472. this.memoStateValue = memoStateValue;
  473. this.minHits = minHits;
  474. }
  475. }
  476. }