/* OrpheusMS: MapleStory Private Server based on OdinMS Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net> Patrick Huy <patrick.huy@frz.cc> Matthias Butz <matze@odinms.de> Jan Christian Meyer <vimes@odinms.de> This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package server.quest; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import client.MapleCharacter; import client.MapleQuestStatus; import client.MapleQuestStatus.Status; import provider.MapleData; import provider.MapleDataProvider; import provider.MapleDataProviderFactory; import provider.MapleDataTool; import tools.MaplePacketCreator; /** * * @author Matze */ public class MapleQuest { private static Map<Integer, MapleQuest> quests = new HashMap<Integer, MapleQuest>(); protected short infoNumber, infoex, id; protected int timeLimit, timeLimit2; protected List<MapleQuestRequirement> startReqs; protected List<MapleQuestRequirement> completeReqs; protected List<MapleQuestAction> startActs; protected List<MapleQuestAction> completeActs; protected List<Integer> relevantMobs; private boolean autoStart; private boolean autoPreComplete; private boolean repeatable = false; private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz")); private static MapleData actions = questData.getData("Act.img"); private static MapleData requirements = questData.getData("Check.img"); private static MapleData info = questData.getData("QuestInfo.img"); private MapleQuest(int id) { this.id = (short) id; relevantMobs = new LinkedList<Integer>(); MapleData startReqData = requirements.getChildByPath(String.valueOf(id)).getChildByPath("0"); startReqs = new LinkedList<MapleQuestRequirement>(); if (startReqData != null) { for (MapleData startReq : startReqData.getChildren()) { MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(startReq.getName()); if (type.equals(MapleQuestRequirementType.INTERVAL)) { repeatable = true; } MapleQuestRequirement req = new MapleQuestRequirement(this, type, startReq); if (req.getType().equals(MapleQuestRequirementType.MOB)) { for (MapleData mob : startReq.getChildren()) { relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id"))); } } startReqs.add(req); } } MapleData completeReqData = requirements.getChildByPath(String.valueOf(id)).getChildByPath("1"); completeReqs = new LinkedList<MapleQuestRequirement>(); if (completeReqData != null) { for (MapleData completeReq : completeReqData.getChildren()) { MapleQuestRequirement req = new MapleQuestRequirement(this, MapleQuestRequirementType.getByWZName(completeReq.getName()), completeReq); if (req.getType().equals(MapleQuestRequirementType.INFO_NUMBER)) infoNumber = (short) MapleDataTool.getInt(completeReq, 0); if (req.getType().equals(MapleQuestRequirementType.INFO_EX)) { MapleData zero = completeReq.getChildByPath("0"); if (zero != null) { MapleData value = zero.getChildByPath("value"); if (value != null) infoex = Short.parseShort(MapleDataTool.getString(value, "0")); } } if (req.getType().equals(MapleQuestRequirementType.MOB)) { for (MapleData mob : completeReq.getChildren()) { relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id"))); } Collections.sort(relevantMobs); } completeReqs.add(req); } } MapleData startActData = actions.getChildByPath(String.valueOf(id)).getChildByPath("0"); startActs = new LinkedList<MapleQuestAction>(); if (startActData != null) { for (MapleData startAct : startActData.getChildren()) { MapleQuestActionType questActionType = MapleQuestActionType.getByWZName(startAct.getName()); startActs.add(new MapleQuestAction(questActionType, startAct, this)); } } MapleData completeActData = actions.getChildByPath(String.valueOf(id)).getChildByPath("1"); completeActs = new LinkedList<MapleQuestAction>(); if (completeActData != null) { for (MapleData completeAct : completeActData.getChildren()) { completeActs.add(new MapleQuestAction(MapleQuestActionType.getByWZName(completeAct.getName()), completeAct, this)); } } MapleData questInfo = info.getChildByPath(String.valueOf(id)); timeLimit = MapleDataTool.getInt("timeLimit", questInfo, 0); timeLimit2 = MapleDataTool.getInt("timeLimit2", questInfo, 0); autoStart = MapleDataTool.getInt("autoStart", questInfo, 0) == 1; autoPreComplete = MapleDataTool.getInt("autoPreComplete", questInfo, 0) == 1; } public static MapleQuest getInstance(int id) { MapleQuest ret = quests.get(id); if (ret == null) { ret = new MapleQuest(id); quests.put(id, ret); } return ret; } private boolean canStart(MapleCharacter c, int npcid) { if (c.getQuest(this).getStatus() != Status.NOT_STARTED && !(c.getQuest(this).getStatus() == Status.COMPLETED && repeatable)) { return false; } for (MapleQuestRequirement r : startReqs) { if (!r.check(c, npcid)) { return false; } } return true; } public boolean canComplete(MapleCharacter c, Integer npcid) { if (!c.getQuest(this).getStatus().equals(Status.STARTED)) { return false; } for (MapleQuestRequirement r : completeReqs) { if (!r.check(c, npcid)) { return false; } } return true; } public void start(MapleCharacter c, int npc) { if ((autoStart || checkNPCOnMap(c, npc)) && canStart(c, npc)) { for (MapleQuestAction a : startActs) { a.run(c, null); } forceStart(c, npc); } } public void complete(MapleCharacter c, int npc) { complete(c, npc, null); } public void complete(MapleCharacter c, int npc, Integer selection) { if ((autoPreComplete || checkNPCOnMap(c, npc)) && canComplete(c, npc)) { /* * for (MapleQuestAction a : completeActs) { if (!a.check(c)) { * return; } } */ forceComplete(c, npc); for (MapleQuestAction a : completeActs) { a.run(c, selection); } } } public void reset(MapleCharacter c) { c.updateQuest(new MapleQuestStatus(this, MapleQuestStatus.Status.NOT_STARTED)); } public void forfeit(MapleCharacter c) { if (!c.getQuest(this).getStatus().equals(Status.STARTED)) { return; } if (timeLimit > 0) { c.announce(MaplePacketCreator.removeQuestTimeLimit(id)); } MapleQuestStatus newStatus = new MapleQuestStatus(this, MapleQuestStatus.Status.NOT_STARTED); newStatus.setForfeited(c.getQuest(this).getForfeited() + 1); c.updateQuest(newStatus); } public boolean forceStart(MapleCharacter c, int npc) { if (!canStart(c, npc)) return false; MapleQuestStatus newStatus = new MapleQuestStatus(this, MapleQuestStatus.Status.STARTED, npc); newStatus.setForfeited(c.getQuest(this).getForfeited()); if (timeLimit > 0) c.questTimeLimit(this, 30000);// timeLimit * 1000 if (timeLimit2 > 0) {// =\ } c.updateQuest(newStatus); return true; } public boolean forceComplete(MapleCharacter c, int npc) { if (!canComplete(c, npc)) return false; MapleQuestStatus newStatus = new MapleQuestStatus(this, MapleQuestStatus.Status.COMPLETED, npc); newStatus.setForfeited(c.getQuest(this).getForfeited()); newStatus.setCompletionTime(System.currentTimeMillis()); c.announce(MaplePacketCreator.showSpecialEffect(9)); c.getMap().broadcastMessage(c, MaplePacketCreator.showForeignEffect(c.getId(), 9), false); c.updateQuest(newStatus); return true; } public short getId() { return id; } public List<Integer> getRelevantMobs() { return relevantMobs; } private boolean checkNPCOnMap(MapleCharacter player, int npcid) { return player.getMap().containsNPC(npcid); } public int getItemAmountNeeded(int itemid) { MapleData data = requirements.getChildByPath(String.valueOf(id)).getChildByPath("1"); if (data != null) { for (MapleData req : data.getChildren()) { MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(req.getName()); if (!type.equals(MapleQuestRequirementType.ITEM)) continue; for (MapleData d : req.getChildren()) { if (MapleDataTool.getInt(d.getChildByPath("id"), 0) == itemid) return MapleDataTool.getInt(d.getChildByPath("count"), 0); } } } return 0; } public int getMobAmountNeeded(int mid) { MapleData data = requirements.getChildByPath(String.valueOf(id)).getChildByPath("1"); if (data != null) { for (MapleData req : data.getChildren()) { MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(req.getName()); if (!type.equals(MapleQuestRequirementType.MOB)) continue; for (MapleData d : req.getChildren()) { if (MapleDataTool.getInt(d.getChildByPath("id"), 0) == mid) return MapleDataTool.getInt(d.getChildByPath("count"), 0); } } } return 0; } public short getInfoNumber() { return infoNumber; } public short getInfoEx() { return infoex; } public int getTimeLimit() { return timeLimit; } }