/* * Copyright © 2004-2019 L2J DataPack * * This file is part of L2J DataPack. * * L2J DataPack is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * L2J DataPack is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package quests.Q00384_WarehouseKeepersPastime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.l2jserver.gameserver.enums.audio.Sound; import com.l2jserver.gameserver.model.actor.L2Npc; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.quest.Quest; import com.l2jserver.gameserver.model.quest.QuestState; import com.l2jserver.gameserver.util.Util; /** * Warehouse Keeper's Pastime (384) * @author Zealar * @since 2.6.0.0 */ public final class Q00384_WarehouseKeepersPastime extends Quest { // NPCs private static final int CLIFF = 30182; private static final int WAREHOUSE_CHIEF_BAXT = 30685; // Monsters private static final int DUST_WIND = 20242; private static final int INNERSEN = 20950; private static final int CONGERER = 20774; private static final int CARINKAIN = 20635; private static final int CONNABI = 20947; private static final int HUNTER_GARGOYLE = 20241; private static final int NIGHTMARE_GUIDE = 20942; private static final int DRAGON_BEARER_WARRIOR = 20759; private static final int DRAGON_BEARER_CHIEF = 20758; private static final int DUST_WIND_HOLD = 20281; private static final int WEIRD_DRAKE = 20605; private static final int THUNDER_WYRM_HOLD = 20282; private static final int CADEINE = 20945; private static final int CONGERER_LORD = 20773; private static final int DRAGON_BEARER_ARCHER = 20760; private static final int NIGHTMARE_LORD = 20944; private static final int SANHIDRO = 20946; private static final int GIANT_MONSTEREYE = 20556; private static final int BARTAL = 20948; private static final int HUNTER_GARGOYLE_HOLD = 20286; private static final int ROT_GOLEM = 20559; private static final int GRAVE_GUARD = 20668; private static final int TULBEN = 20677; private static final int NIGHTMARE_KEEPER = 20943; private static final int LUMINUN = 20949; private static final int THUNDER_WYRM = 20243; // Items private static final int Q_IRONGATE_MEDAL = 5964; // Reward private static final int MOONSTONE_EARING = 852; private static final int DRAKE_LEATHER_BOOTS = 2437; private static final int DRAKE_LEATHER_MAIL = 401; private static final int MOLD_HARDENER = 4041; private static final int NECKLACE_OF_MERMAID = 917; private static final int SCRL_OF_ENCH_AM_C = 952; private static final int BLACKSMITH_S_FRAME = 1892; private static final int SCRL_OF_ENCH_WP_C = 951; private static final int ORIHARUKON = 1893; private static final int SAMURAI_LONGSWORD = 135; private static final int AQUASTONE_RING = 883; private static final int SYNTHESIS_COKES = 1888; private static final int MITHIRL_ALLOY = 1890; private static final int GREAT_HELMET = 500; private static final int VARNISH_OF_PURITY = 1887; private static final int BLESSED_GLOVES = 2463; private static final int CRAFTED_LEATHER = 1894; public Q00384_WarehouseKeepersPastime() { super(384, Q00384_WarehouseKeepersPastime.class.getSimpleName(), "Warehouse Keeper's Pastime"); addStartNpc(CLIFF); addTalkId(CLIFF, WAREHOUSE_CHIEF_BAXT); addKillId(WAREHOUSE_CHIEF_BAXT, DUST_WIND, INNERSEN, CLIFF, CONGERER, CARINKAIN, CONNABI, HUNTER_GARGOYLE, NIGHTMARE_GUIDE, DRAGON_BEARER_WARRIOR, DRAGON_BEARER_CHIEF, DUST_WIND_HOLD, WEIRD_DRAKE, THUNDER_WYRM_HOLD, CADEINE, CONGERER_LORD, DRAGON_BEARER_ARCHER, NIGHTMARE_LORD, SANHIDRO, GIANT_MONSTEREYE, BARTAL, HUNTER_GARGOYLE_HOLD, ROT_GOLEM, GRAVE_GUARD, TULBEN, NIGHTMARE_KEEPER, LUMINUN, THUNDER_WYRM); registerQuestItems(Q_IRONGATE_MEDAL); } @Override public String onTalk(L2Npc npc, L2PcInstance player) { final QuestState qs = getQuestState(player, true); String htmltext = getNoQuestMsg(player); switch (npc.getId()) { case CLIFF: if (qs.isCreated()) { if (player.getLevel() >= 40) { return "30182-01.htm"; } return "30182-04.html"; } if (qs.getQuestItemsCount(Q_IRONGATE_MEDAL) < 10) { return "30182-06.html"; } return "30182-07.html"; case WAREHOUSE_CHIEF_BAXT: if (qs.hasMemoState()) { if (qs.getQuestItemsCount(Q_IRONGATE_MEDAL) < 10) { return "30685-06.html"; } return "30685-07.html"; } } return htmltext; } @Override public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) { final QuestState qs = getQuestState(player, false); if ((qs != null)) { if (event.contains(".htm")) { return event; } switch (npc.getId()) { case CLIFF: { if (event.equals("QUEST_ACCEPTED")) { qs.playSound(Sound.ITEMSOUND_QUEST_ACCEPT); qs.setMemoState(384); qs.startQuest(); qs.showQuestionMark(384); qs.playSound(Sound.ITEMSOUND_QUEST_MIDDLE); return "30182-05.htm"; } final int ask = Integer.parseInt(event); switch (ask) { case 3: return "30182-09a.htm"; case 4: return "30182-02.htm"; case 5: if (npc.getId() != CLIFF) { return getNoQuestMsg(player); } return "30182-03.htm"; case 6: { qs.exitQuest(true); return "30182-08.html"; } case 9: return "30182-09.html"; case 7: { if (qs.getQuestItemsCount(Q_IRONGATE_MEDAL) >= 10) { qs.takeItems(Q_IRONGATE_MEDAL, 10); qs.setMemoState(10); createBingoBoard(qs); return "30182-10.html"; } return "30182-11.html"; } case 8: { if (qs.getQuestItemsCount(Q_IRONGATE_MEDAL) >= 100) { qs.takeItems(Q_IRONGATE_MEDAL, 100); qs.setMemoState(20); createBingoBoard(qs); return "30182-12.html"; } return "30182-11.html"; } case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: { selectBingoNumber(qs, (ask - 10) + 1); return fillBoard(player, qs, getHtm(player.getHtmlPrefix(), "30182-13.html")); } case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: { return takeHtml(player, qs, (ask - 18), CLIFF); } case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: { return beforeReward(player, qs, (ask - 54), CLIFF); } } break; } case WAREHOUSE_CHIEF_BAXT: final int ask = Integer.parseInt(event); switch (ask) { case 3: return "30685-09a.html"; case 6: qs.exitQuest(true); return "30685-08.html"; case 9: return "30685-09.html"; case 7: if (qs.getQuestItemsCount(Q_IRONGATE_MEDAL) >= 10) { qs.takeItems(Q_IRONGATE_MEDAL, 10); qs.setMemoState(10); createBingoBoard(qs); return "30685-10.html"; } return "30685-11.html"; case 8: if (qs.getQuestItemsCount(Q_IRONGATE_MEDAL) >= 100) { qs.takeItems(Q_IRONGATE_MEDAL, 100); qs.setMemoState(20); createBingoBoard(qs); return "30685-12.html"; } return "30685-11.html"; case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: { selectBingoNumber(qs, (ask - 9)); return fillBoard(player, qs, getHtm(player.getHtmlPrefix(), "30685-13.html")); } case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: { return takeHtml(player, qs, (ask - 18), WAREHOUSE_CHIEF_BAXT); } case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: { return beforeReward(player, qs, (ask - 54), WAREHOUSE_CHIEF_BAXT); } } } } return super.onAdvEvent(event, npc, player); } private String takeHtml(L2PcInstance player, QuestState qs, int num, int npcId) { String html = null; int i3; if (!isSelectedBingoNumber(qs, num)) { selectBingoNumber(qs, num); i3 = getBingoSelectCount(qs); if (i3 == 2) { html = getHtm(player.getHtmlPrefix(), npcId + "-14.html"); } else if (i3 == 3) { html = getHtm(player.getHtmlPrefix(), npcId + "-16.html"); } else if (i3 == 4) { html = getHtm(player.getHtmlPrefix(), npcId + "-18.html"); } else if (i3 == 5) { html = getHtm(player.getHtmlPrefix(), npcId + "-20.html"); } return fillBoard(player, qs, html); } i3 = getBingoSelectCount(qs); if (i3 == 1) { html = getHtm(player.getHtmlPrefix(), npcId + "-15.html"); } else if (i3 == 2) { html = getHtm(player.getHtmlPrefix(), npcId + "-17.html"); } else if (i3 == 3) { html = getHtm(player.getHtmlPrefix(), npcId + "-19.html"); } else if (i3 == 4) { html = getHtm(player.getHtmlPrefix(), npcId + "-21.html"); } return fillBoard(player, qs, html); } private String fillBoard(L2PcInstance player, QuestState qs, String html) { for (int i0 = 0; i0 < 9; i0 = i0 + 1) { int i1 = getNumberFromBingoBoard(qs, i0); if (isSelectedBingoNumber(qs, i1)) { html = html.replace("<?Cell" + (i0 + 1) + "?>", i1 + ""); } else { html = html.replace("<?Cell" + (i0 + 1) + "?>", "?"); } } return html; } private String colorBoard(L2PcInstance player, QuestState qs, String html) { for (int i0 = 0; i0 < 9; i0 = i0 + 1) { int i1 = getNumberFromBingoBoard(qs, i0); html = html.replace("<?FontColor" + (i0 + 1) + "?>", (isSelectedBingoNumber(qs, i1)) ? "ff0000" : "ffffff"); html = html.replace("<?Cell" + (i0 + 1) + "?>", i1 + ""); } return html; } private String beforeReward(L2PcInstance player, QuestState qs, int num, int npcId) { if (!isSelectedBingoNumber(qs, num)) { selectBingoNumber(qs, num); int i3 = getMatchedBingoLineCount(qs); String html; if ((i3 == 3) && ((getBingoSelectCount(qs)) == 6)) { reward(player, qs, i3); html = getHtm(player.getHtmlPrefix(), npcId + "-22.html"); } else if ((i3 == 0) && (getBingoSelectCount(qs) == 6)) { reward(player, qs, i3); html = getHtm(player.getHtmlPrefix(), npcId + "-24.html"); } else { html = getHtm(player.getHtmlPrefix(), npcId + "-23.html"); } return colorBoard(player, qs, html); } return fillBoard(player, qs, getHtm(player.getHtmlPrefix(), npcId + "-25.html")); } private void reward(L2PcInstance player, QuestState qs, int i3) { if (i3 == 3) { if (qs.getMemoState() == 10) { int random = getRandom(100); if (random < 16) { qs.giveItems(SYNTHESIS_COKES, 1); } else if (random < 32) { qs.giveItems(VARNISH_OF_PURITY, 1); } else if (random < 50) { qs.giveItems(CRAFTED_LEATHER, 1); } else if (random < 80) { qs.giveItems(SCRL_OF_ENCH_AM_C, 1); } else if (random < 89) { qs.giveItems(MITHIRL_ALLOY, 1); } else if (random < 98) { qs.giveItems(ORIHARUKON, 1); } else { qs.giveItems(SCRL_OF_ENCH_WP_C, 1); } } else if (qs.getMemoState() == 20) { int random = getRandom(100); if (random < 50) { qs.giveItems(AQUASTONE_RING, 1); } else if (random < 80) { qs.giveItems(SCRL_OF_ENCH_WP_C, 1); } else if (random < 98) { qs.giveItems(MOONSTONE_EARING, 1); } else { qs.giveItems(DRAKE_LEATHER_MAIL, 1); } } } else if (i3 == 0) { if (qs.getMemoState() == 10) { int random = getRandom(100); if (random < 50) { qs.giveItems(MOLD_HARDENER, 1); } else if (random < 80) { qs.giveItems(SCRL_OF_ENCH_AM_C, 1); } else if (random < 98) { qs.giveItems(BLACKSMITH_S_FRAME, 1); } else { qs.giveItems(NECKLACE_OF_MERMAID, 1); } } else if (qs.getMemoState() == 20) { int random = getRandom(100); if (random < 50) { qs.giveItems(SCRL_OF_ENCH_WP_C, 1); } else if (random < 80) { qs.giveItems(GREAT_HELMET, 1); } else if (random < 98) { qs.giveItems(DRAKE_LEATHER_BOOTS, 1); qs.giveItems(BLESSED_GLOVES, 1); } else { qs.giveItems(SAMURAI_LONGSWORD, 1); } } } } /** * @param qs */ private void createBingoBoard(QuestState qs) { //@formatter:off Integer[] arr = {1,2,3,4,5,6,7,8,9}; //@formatter:on Collections.shuffle(Arrays.asList(arr)); qs.set("numbers", Arrays.asList(arr).toString().replaceAll("[^\\d ]", "")); qs.set("selected", "? ? ? ? ? ? ? ? ?"); } /** * @param qs * @return */ private int getMatchedBingoLineCount(QuestState qs) { String[] q = qs.get("selected").split(" "); int found = 0; // Horizontal if ((q[0] + q[1] + q[2]).matches("\\d+")) { found++; } if ((q[3] + q[4] + q[5]).matches("\\d+")) { found++; } if ((q[6] + q[7] + q[8]).matches("\\d+")) { found++; } // Vertical if ((q[0] + q[3] + q[6]).matches("\\d+")) { found++; } if ((q[1] + q[4] + q[7]).matches("\\d+")) { found++; } if ((q[2] + q[5] + q[8]).matches("\\d+")) { found++; } // Diagonal if ((q[0] + q[4] + q[8]).matches("\\d+")) { found++; } if ((q[2] + q[4] + q[6]).matches("\\d+")) { found++; } return found; } /** * @param qs * @param num */ private void selectBingoNumber(QuestState qs, int num) { String[] numbers = qs.get("numbers").split(" "); int pos = 0; for (int i = 0; i < numbers.length; i++) { if (Integer.parseInt(numbers[i]) == num) { pos = i; break; } } String[] selected = qs.get("selected").split(" "); for (int i = 0; i < selected.length; i++) { if (i == pos) { selected[i] = num + ""; continue; } } String result = selected[0]; for (int i = 1; i < selected.length; i++) { result += " " + selected[i]; } qs.set("selected", result); } /** * @param qs * @param num * @return */ private boolean isSelectedBingoNumber(QuestState qs, int num) { return qs.get("selected").contains(num + ""); } /** * @param qs * @param num * @return */ private int getNumberFromBingoBoard(QuestState qs, int num) { return Integer.parseInt(qs.get("numbers").split(" ")[num]); } /** * @param qs * @return */ private int getBingoSelectCount(QuestState qs) { String current = qs.get("selected"); return current.replaceAll("\\D", "").length(); } @Override public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) { final QuestState qs = getRandomPlayerFromParty(killer, npc); if (qs != null) { switch (npc.getId()) { case HUNTER_GARGOYLE: if (getRandom(1000) < 328) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case DUST_WIND: if (getRandom(100) < 35) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case THUNDER_WYRM: if (getRandom(1000) < 312) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case DUST_WIND_HOLD: if (getRandom(100) < 35) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case THUNDER_WYRM_HOLD: if (getRandom(1000) < 312) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case HUNTER_GARGOYLE_HOLD: if (getRandom(1000) < 328) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case GIANT_MONSTEREYE: if (getRandom(1000) < 176) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case ROT_GOLEM: if (getRandom(1000) < 226) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case WEIRD_DRAKE: if (getRandom(1000) < 218) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case CARINKAIN: if (getRandom(1000) < 216) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case GRAVE_GUARD: if (getRandom(1000) < 312) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case TULBEN: if (getRandom(1000) < 522) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case DRAGON_BEARER_CHIEF: if (getRandom(100) < 38) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case DRAGON_BEARER_WARRIOR: if (getRandom(100) < 39) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case DRAGON_BEARER_ARCHER: if (getRandom(1000) < 372) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case CONGERER_LORD: if (getRandom(1000) < 802) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case CONGERER: if (getRandom(1000) < 844) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case NIGHTMARE_GUIDE: if (getRandom(1000) < 118) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case NIGHTMARE_KEEPER: if (getRandom(100) < 17) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case NIGHTMARE_LORD: if (getRandom(1000) < 144) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case CADEINE: if (getRandom(1000) < 162) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case SANHIDRO: if (getRandom(100) < 25) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case CONNABI: if (getRandom(1000) < 272) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case BARTAL: if (getRandom(100) < 27) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case LUMINUN: if (getRandom(100) < 32) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; case INNERSEN: if (getRandom(1000) < 346) { giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true); } break; } } return super.onKill(npc, killer, isSummon); } private QuestState getRandomPlayerFromParty(L2PcInstance player, L2Npc npc) { QuestState qs = getQuestState(player, false); final List<QuestState> candidates = new ArrayList<>(); if ((qs != null) && qs.isStarted()) { candidates.add(qs); candidates.add(qs); } if (player.isInParty()) { player.getParty().getMembers().stream().forEach(pm -> { QuestState qss = getQuestState(pm, false); if ((qss != null) && qss.isStarted() && Util.checkIfInRange(1500, npc, pm, true)) { candidates.add(qss); } }); } return candidates.isEmpty() ? null : candidates.get(getRandom(candidates.size())); } }