package handling.channel.handler; import client.MapleCharacter; import client.MapleClient; import client.MapleQuestStatus; import client.RockPaperScissors; import client.inventory.Equip; import client.inventory.Item; import client.inventory.ItemFlag; import client.inventory.MapleInventoryType; import constants.GameConstants; import constants.ItemConstants; import handling.SendPacketOpcode; import handling.world.WorldBroadcastService; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.log4j.Logger; import scripting.item.ItemScriptManager; import scripting.npc.NPCConversationManager; import scripting.npc.NPCScriptManager; import scripting.quest.QuestScriptManager; import server.AutobanManager; import server.MapleInventoryManipulator; import server.MapleItemInformationProvider; import server.MapleStorage; import server.ServerProperties; import server.life.MapleNPC; import server.maps.MapScriptMethods; import server.maps.MapleQuickMove; import server.quest.MapleQuest; import server.shop.MapleShop; import tools.FileoutputUtil; import tools.MaplePacketCreator; import tools.Pair; import tools.data.input.SeekableLittleEndianAccessor; import tools.data.output.MaplePacketLittleEndianWriter; import tools.packet.NPCPacket; public class NPCHandler { public static void NPCAnimation(SeekableLittleEndianAccessor slea, MapleClient c) { MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); mplew.write(SendPacketOpcode.NPC_ACTION.getValue()); int length = (int) slea.available(); if (length == 6) { mplew.writeInt(slea.readInt()); mplew.writeShort(slea.readShort()); } else{ mplew.write(slea.read(length)); } c.getSession().write(mplew.getPacket()); } /** * NPC 商店操作 * @param slea * @param c * @param chr */ public static void NPCShop(SeekableLittleEndianAccessor slea, MapleClient c, MapleCharacter chr) { // 25 00 00 00 60 4A 0F 00 01 00 // 25 00 01 00 80 84 1E 00 01 00 // 25 03 byte bmode = slea.readByte(); if (chr == null) { return; } switch (bmode) { case 0://购买 MapleShop shop = chr.getShop(); if (shop == null) { return; } short position = slea.readShort(); int itemId = slea.readInt(); short quantity = slea.readShort(); shop.buy(c, itemId, quantity, position); break; case 1://出售 shop = chr.getShop(); if (shop == null) { return; } byte slot = (byte) slea.readShort(); itemId = slea.readInt(); quantity = slea.readShort(); shop.sell(c, ItemConstants.getInventoryType(itemId), slot, quantity); break; case 2://充值 shop = chr.getShop(); if (shop == null) { return; } slot = (byte) slea.readShort(); shop.recharge(c, slot); break; default: chr.setConversation(0);break; } } public static void NPCTalk(SeekableLittleEndianAccessor slea, MapleClient c, MapleCharacter chr) { if ((chr == null) || (chr.getMap() == null)) { return; } MapleNPC npc = chr.getMap().getNPCByOid(slea.readInt()); if (npc == null) { return; } if (chr.hasBlockedInventory()) { chr.dropMessage(5, "现在不能进行操作。"); c.getSession().write(MaplePacketCreator.enableActions()); return; } if (npc.hasShop()) { chr.setConversation(1); npc.sendShop(c); } else if (npc.isStorage()) { c.getPlayer().getStorage().sendStorage(c, npc.getId()); } else if (npc.hasQuest(chr)) { // 检查是否有任务可以开始 MapleQuest quest = MapleQuest.getInstance(npc.getQuestId()); if (quest == null) { chr.dropMessage(0,"未知的任务:"+npc.getQuestId()+"!"); } else { chr.addQuest(quest); chr.dropMessage(0,"恭喜开始任务:"+quest.getName()+"!赶紧打开任务面板查看任务信息吧!"); } } else if (npc.hasCompleteQuest(chr)) { } else { chr.dropMessage(5,"当前对话NPC:"+npc.getId()); NPCScriptManager.getInstance().start(c, npc.getId()); } } public static void QuestAction(SeekableLittleEndianAccessor slea, MapleClient c, MapleCharacter chr) { byte action = slea.readByte(); int quest = slea.readUShort(); if (chr == null) { return; } boolean 冰峰雪域的长老任务; switch (quest) { case 1430: case 1434: case 1438: case 1441: case 1444: 冰峰雪域的长老任务 = true; break; default: 冰峰雪域的长老任务 = false; } if (冰峰雪域的长老任务 && c.getPlayer().getQuestStatus(quest) != 1 && c.getPlayer().getMapId() != 211000001) {//冒险家3转传送 final server.maps.MapleMap mapz = handling.channel.ChannelServer.getInstance(c.getChannel()).getMapFactory().getMap(211000001); c.getPlayer().changeMap(mapz, mapz.getPortal(0)); } MapleQuest q = MapleQuest.getInstance(quest); switch (action) { case 0: slea.readInt(); int itemid = slea.readInt(); q.RestoreLostItem(chr, itemid); break; case 1: int npc = slea.readInt(); if (q.hasStartScript()) { break; } q.start(chr, npc); if (!chr.isShowPacket()) { break; } chr.dropMessage(6, "开始系统任务 NPC: " + npc + " Quest:" + quest); break; case 2: npc = slea.readInt(); slea.readInt(); if (q.hasEndScript()) { return; } if (slea.available() >= 4L) { q.complete(chr, npc, slea.readInt()); } else { q.complete(chr, npc); } if (!chr.isShowPacket()) { break; } chr.dropMessage(6, "完成系统任务 NPC: " + npc + " Quest: " + quest); break; case 3: if (GameConstants.canForfeit(q.getId())) { q.forfeit(chr); if (!chr.isShowPacket()) { break; } chr.dropMessage(6, "放弃系统任务 Quest: " + quest); } else { chr.dropMessage(1, "无法放弃这个任务."); } break; case 4: npc = slea.readInt(); if (chr.hasBlockedInventory()) { c.getSession().write(MaplePacketCreator.enableActions()); return; } QuestScriptManager.getInstance().startQuest(c, npc, quest); if ((!chr.isAdmin()) || (!ServerProperties.ShowPacket())) { break; } chr.dropMessage(6, "执行脚本任务 NPC:" + npc + " Quest: " + quest); break; case 5: npc = slea.readInt(); if (chr.hasBlockedInventory()) { c.getSession().write(MaplePacketCreator.enableActions()); return; } QuestScriptManager.getInstance().endQuest(c, npc, quest, false); // c.getSession().write(MaplePacketCreator.showSpecialEffect(13)); // chr.getMap().broadcastMessage(chr, MaplePacketCreator.showSpecialEffect(chr.getId(), 13), false); if (!chr.isShowPacket()) { break; } chr.dropMessage(6, "完成脚本任务 NPC:" + npc + " Quest: " + quest); break; } } /** * 仓库包处理 * @param slea * @param c * @param chr */ public static void Storage(SeekableLittleEndianAccessor slea, MapleClient c, MapleCharacter chr) { byte mode = slea.readByte(); if (chr == null) { return; } MapleStorage storage = chr.getStorage(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); switch (mode) { case 4://取出 byte type = slea.readByte(); byte slot = slea.readByte(); // 从0开始计算的 slot = storage.getSlot(MapleInventoryType.getByType(type), slot); Item item = storage.getItem(slot); if (item != null) { if ((ii.isPickupRestricted(item.getItemId())) && (chr.getItemQuantity(item.getItemId(), true) > 0)) { c.getSession().write(NPCPacket.getStorageError((byte) 9)); return; } long meso = (storage.getNpcId() == 9030100) || (storage.getNpcId() == 9031016) ? 1000 : 0; if (chr.getMeso() < meso) { c.getSession().write(NPCPacket.getStorageError((byte) 13)); return; } if (MapleInventoryManipulator.checkSpace(c, item.getItemId(), item.getQuantity(), item.getOwner())) { item = storage.takeOut(slot); short flag = item.getFlag(); if (ItemFlag.KARMA_USE.check(flag)) { item.setFlag((short) (flag - ItemFlag.KARMA_USE.getValue())); } MapleInventoryManipulator.addFromDrop(c, item, false); if (meso > 0) { chr.gainMeso(-meso, false); } storage.sendTakenOut(c, ItemConstants.getInventoryType(item.getItemId())); } else { c.getSession().write(NPCPacket.getStorageError((byte) 9)); } } else { FileoutputUtil.log("[作弊] " + chr.getName() + " (等级 " + chr.getLevel() + ") 试图从仓库取出不存在的道具."); WorldBroadcastService.getInstance().broadcastGMMessage(MaplePacketCreator.serverMessageRedText("[GM 信息] 玩家: " + chr.getName() + " (等级 " + chr.getLevel() + ") 试图从仓库取出不存在的道具.")); c.getSession().write(MaplePacketCreator.enableActions()); } break; case 5://放入仓库 slot = (byte) slea.readShort(); int itemId = slea.readInt(); short quantity = slea.readShort(); if (quantity < 1) { AutobanManager.getInstance().autoban(c, "试图存入到仓库的道具数量: " + quantity + " 道具ID: " + itemId); return; } if (storage.isFull()) { c.getSession().write(NPCPacket.getStorageError((byte) 9)); return; } MapleInventoryType type1 = ItemConstants.getInventoryType(itemId); if (chr.getInventory(type1).getItem((short) slot) == null) { c.getSession().write(MaplePacketCreator.enableActions()); return; } long meso = (storage.getNpcId() == 9030100) || (storage.getNpcId() == 9031016) ? 500 : 100; if (chr.getMeso() < meso) { c.getSession().write(NPCPacket.getStorageError((byte) 13)); return; } item = chr.getInventory(type1).getItem((short) slot).copy(); if (ItemConstants.isPet(item.getItemId())) { c.getSession().write(MaplePacketCreator.enableActions()); return; } if ((ii.isPickupRestricted(item.getItemId())) && (storage.findById(item.getItemId()) != null)) { c.getSession().write(MaplePacketCreator.enableActions()); return; } if ((item.getItemId() == itemId) && ((item.getQuantity() >= quantity) || (ItemConstants.isRechargable(itemId)))) { if (ItemConstants.isRechargable(itemId)) { quantity = item.getQuantity(); } chr.gainMeso(-meso, false, false); MapleInventoryManipulator.removeFromSlot(c, type1, (short) slot, quantity, false); item.setQuantity(quantity); storage.store(item); storage.sendStored(c, ItemConstants.getInventoryType(itemId)); } else { AutobanManager.getInstance().addPoints(c, 1000, 0L, "试图存入到仓库的道具: " + itemId + " 数量: " + quantity + " 当前玩家用道具: " + item.getItemId() + " 数量: " + item.getQuantity()); } break; case 6: meso = slea.readInt(); long storageMesos = storage.getMeso(); long playerMesos = chr.getMeso(); if (((meso > 0) && (storageMesos >= meso)) || ((meso < 0) && (playerMesos >= -meso))) { if ((meso < 0) && (storageMesos - meso < 0)) { meso = -(9999999999L - storageMesos); if (-meso > playerMesos) { return; } } else if ((meso > 0) && (playerMesos + meso < 0)) { meso = 9999999999L - playerMesos; if (meso > storageMesos) { return; } } storage.setMeso(storageMesos - meso); chr.gainMeso(meso, false, false); } else { AutobanManager.getInstance().addPoints(c, 1000, 0L, "Trying to store or take out unavailable amount of mesos (" + meso + "/" + storage.getMeso() + "/" + c.getPlayer().getMeso() + ")"); return; } storage.sendMeso(c); break; case 7: storage.close(); chr.setConversation(0); break; default: FileoutputUtil.log("Unhandled Storage mode : " + mode); } } /** * NPC第二次对话 * @param slea * @param c */ public static void NPCMoreTalk(SeekableLittleEndianAccessor slea, MapleClient c) { MapleCharacter player = c.getPlayer(); if (player == null) { return; } final NPCConversationManager cm = NPCScriptManager.getInstance().getCM(c); byte lastMsg = slea.readByte(); byte action = slea.readByte(); if (player.getConversation() != 1) { return; } if (lastMsg == 3) { // 数字框 int selection = -1; if (slea.available() >= 4L) { selection = slea.readInt(); } else if (slea.available() > 0L) { selection = slea.readByte(); } if ((!player.isShowPacket()) || ((selection >= -1) && (action != -1))) { if (c.getQM() != null) { if (c.getQM().isStart()) { QuestScriptManager.getInstance().startAction(c, action, lastMsg, selection); } else { QuestScriptManager.getInstance().endAction(c, action, lastMsg, selection); } } else if (c.getIM() != null) { ItemScriptManager.getInstance().action(c, action, lastMsg, selection); } else if (c.getCM() != null) { NPCScriptManager.getInstance().action(c, action, lastMsg, selection); } } else { if (c.getQM() != null) { c.getQM().dispose(); } if (c.getIM() != null) { c.getIM().dispose(); } if (c.getCM() != null) { c.getCM().dispose(); } } } else { int selection = -1; if (slea.available() >= 4L) { selection = slea.readInt(); } else if (slea.available() > 0L) { selection = slea.readByte(); } if ((!player.isShowPacket()) || ((selection >= -1) && (action != -1))) { if (c.getQM() != null) { if (c.getQM().isStart()) { QuestScriptManager.getInstance().startAction(c, action, lastMsg, selection); } else { QuestScriptManager.getInstance().endAction(c, action, lastMsg, selection); } } else if (c.getIM() != null) { ItemScriptManager.getInstance().action(c, action, lastMsg, selection); } else if (c.getCM() != null) { NPCScriptManager.getInstance().action(c, action, lastMsg, selection); } } else { if (c.getQM() != null) { c.getQM().dispose(); } if (c.getIM() != null) { c.getIM().dispose(); } if (c.getCM() != null) { c.getCM().dispose(); } } } } public static void UpdateQuest(SeekableLittleEndianAccessor slea, MapleClient c) { MapleQuest quest = MapleQuest.getInstance(slea.readShort()); if (quest != null) { c.getPlayer().updateQuest(c.getPlayer().getQuest(quest), true); } } public static void UseItemQuest(SeekableLittleEndianAccessor slea, MapleClient c) { short slot = slea.readShort(); int itemId = slea.readInt(); Item item = c.getPlayer().getInventory(MapleInventoryType.ETC).getItem(slot); int qid = slea.readInt(); MapleQuest quest = MapleQuest.getInstance(qid); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); Pair questItemInfo = null; boolean found = false; for (Item i : c.getPlayer().getInventory(MapleInventoryType.ETC)) { if (i.getItemId() / 10000 == 422) { questItemInfo = ii.questItemInfo(i.getItemId()); if ((questItemInfo != null) && (((Integer) questItemInfo.getLeft()) == qid) && (questItemInfo.getRight() != null) && (((List) questItemInfo.getRight()).contains(itemId))) { found = true; break; } } } if ((quest != null) && (found) && (item != null) && (item.getQuantity() > 0) && (item.getItemId() == itemId)) { int newData = slea.readInt(); MapleQuestStatus stats = c.getPlayer().getQuestNoAdd(quest); if ((stats != null) && (stats.getStatus() == 1)) { stats.setCustomData(String.valueOf(newData)); c.getPlayer().updateQuest(stats, true); MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.ETC, slot, (short) 1, false); } } } public static void RPSGame(SeekableLittleEndianAccessor slea, MapleClient c) { if ((slea.available() == 0L) || (c.getPlayer() == null) || (c.getPlayer().getMap() == null) || (!c.getPlayer().getMap().containsNPC(9000019))) { if ((c.getPlayer() != null) && (c.getPlayer().getRPS() != null)) { c.getPlayer().getRPS().dispose(c); } return; } byte mode = slea.readByte(); switch (mode) { case 0: case 5: if (c.getPlayer().getRPS() != null) { c.getPlayer().getRPS().reward(c); } if (c.getPlayer().getMeso() >= 1000) { c.getPlayer().setRPS(new RockPaperScissors(c, mode)); } else { c.getSession().write(MaplePacketCreator.getRPSMode((byte) 8, -1, -1, -1)); } break; case 1: if ((c.getPlayer().getRPS() != null) && (c.getPlayer().getRPS().answer(c, slea.readByte()))) { break; } c.getSession().write(MaplePacketCreator.getRPSMode((byte) 13, -1, -1, -1)); break; case 2: if ((c.getPlayer().getRPS() != null) && (c.getPlayer().getRPS().timeOut(c))) { break; } c.getSession().write(MaplePacketCreator.getRPSMode((byte) 13, -1, -1, -1)); break; case 3: if ((c.getPlayer().getRPS() != null) && (c.getPlayer().getRPS().nextRound(c))) { break; } c.getSession().write(MaplePacketCreator.getRPSMode((byte) 13, -1, -1, -1)); break; case 4: if (c.getPlayer().getRPS() != null) { c.getPlayer().getRPS().dispose(c); } else { c.getSession().write(MaplePacketCreator.getRPSMode((byte) 13, -1, -1, -1)); } } } }