/* 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; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import client.Equip; import client.IEquip; import client.IItem; import client.MapleCharacter; import client.MapleClient; import client.MapleInventory; import client.MapleInventoryType; import client.MapleJob; import client.MapleWeaponType; import client.SkillFactory; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import constants.ItemConstants; import java.util.Collection; import java.util.LinkedList; import tools.Randomizer; import provider.MapleData; import provider.MapleDataDirectoryEntry; import provider.MapleDataFileEntry; import provider.MapleDataProvider; import provider.MapleDataProviderFactory; import provider.MapleDataTool; import tools.DatabaseConnection; import tools.Pair; /** * * @author Matze * */ public class MapleItemInformationProvider { private static MapleItemInformationProvider instance = null; protected MapleDataProvider itemData; protected MapleDataProvider equipData; protected MapleDataProvider stringData; protected MapleData cashStringData; protected MapleData consumeStringData; protected MapleData eqpStringData; protected MapleData etcStringData; protected MapleData insStringData; protected MapleData petStringData; protected Map<Integer, MapleInventoryType> inventoryTypeCache = new HashMap<Integer, MapleInventoryType>(); protected Map<Integer, Short> slotMaxCache = new HashMap<Integer, Short>(); protected Map<Integer, MapleStatEffect> itemEffects = new HashMap<Integer, MapleStatEffect>(); protected Map<Integer, Map<String, Integer>> equipStatsCache = new HashMap<Integer, Map<String, Integer>>(); protected Map<Integer, Equip> equipCache = new HashMap<Integer, Equip>(); protected Map<Integer, Double> priceCache = new HashMap<Integer, Double>(); protected Map<Integer, Integer> wholePriceCache = new HashMap<Integer, Integer>(); protected Map<Integer, Integer> projectileWatkCache = new HashMap<Integer, Integer>(); protected Map<Integer, String> nameCache = new HashMap<Integer, String>(); protected Map<Integer, String> descCache = new HashMap<Integer, String>(); protected Map<Integer, String> msgCache = new HashMap<Integer, String>(); protected Map<Integer, Boolean> dropRestrictionCache = new HashMap<Integer, Boolean>(); protected Map<Integer, Boolean> pickupRestrictionCache = new HashMap<Integer, Boolean>(); protected Map<Integer, Integer> getMesoCache = new HashMap<Integer, Integer>(); protected Map<Integer, Integer> monsterBookID = new HashMap<Integer, Integer>(); protected Map<Integer, Boolean> onEquipUntradableCache = new HashMap<Integer, Boolean>(); protected Map<Integer, scriptedItem> scriptedItemCache = new HashMap<Integer, scriptedItem>(); protected Map<Integer, Boolean> karmaCache = new HashMap<Integer, Boolean>(); protected Map<Integer, Integer> triggerItemCache = new HashMap<Integer, Integer>(); protected Map<Integer, Integer> expCache = new HashMap<Integer, Integer>(); protected Map<Integer, Integer> levelCache = new HashMap<Integer, Integer>(); protected Map<Integer, Pair<Integer, List<RewardItem>>> rewardCache = new HashMap<Integer, Pair<Integer, List<RewardItem>>>(); protected List<ItemNameEntry> itemNameCache = new ArrayList<ItemNameEntry>(); protected Map<Integer, Boolean> consumeOnPickupCache = new HashMap<Integer, Boolean>(); protected Map<Integer, Boolean> isQuestItemCache = new HashMap<Integer, Boolean>(); private MapleItemInformationProvider() { loadCardIdData(); itemData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Item.wz")); equipData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Character.wz")); stringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz")); cashStringData = stringData.getData("Cash.img"); consumeStringData = stringData.getData("Consume.img"); eqpStringData = stringData.getData("Eqp.img"); etcStringData = stringData.getData("Etc.img"); insStringData = stringData.getData("Ins.img"); petStringData = stringData.getData("Pet.img"); } public static MapleItemInformationProvider getInstance() { if (instance == null) { instance = new MapleItemInformationProvider(); } return instance; } public MapleInventoryType getInventoryType(int itemId) { if (inventoryTypeCache.containsKey(itemId)) { return inventoryTypeCache.get(itemId); } MapleInventoryType ret; String idStr = "0" + String.valueOf(itemId); MapleDataDirectoryEntry root = itemData.getRoot(); for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) { for (MapleDataFileEntry iFile : topDir.getFiles()) { if (iFile.getName().equals(idStr.substring(0, 4) + ".img")) { ret = MapleInventoryType.getByWZName(topDir.getName()); inventoryTypeCache.put(itemId, ret); return ret; } else if (iFile.getName().equals(idStr.substring(1) + ".img")) { ret = MapleInventoryType.getByWZName(topDir.getName()); inventoryTypeCache.put(itemId, ret); return ret; } } } root = equipData.getRoot(); for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) { for (MapleDataFileEntry iFile : topDir.getFiles()) { if (iFile.getName().equals(idStr + ".img")) { ret = MapleInventoryType.EQUIP; inventoryTypeCache.put(itemId, ret); return ret; } } } ret = MapleInventoryType.UNDEFINED; inventoryTypeCache.put(itemId, ret); return ret; } public List<ItemNameEntry> getAllItems() { // BUG: If you never add anything to this, it'll always be empty, duh? if (!itemNameCache.isEmpty()) { return itemNameCache; } List<ItemNameEntry> entries = new ArrayList<ItemNameEntry>(); MapleData itemsData; itemsData = stringData.getData("Cash.img"); for (MapleData itemFolder : itemsData.getChildren()) { entries.add(getItemNameEntry(itemFolder)); } itemsData = stringData.getData("Consume.img"); for (MapleData itemFolder : itemsData.getChildren()) { entries.add(getItemNameEntry(itemFolder)); } itemsData = stringData.getData("Eqp.img").getChildByPath("Eqp"); for (MapleData eqpType : itemsData.getChildren()) { for (MapleData itemFolder : eqpType.getChildren()) { entries.add(getItemNameEntry(itemFolder)); } } itemsData = stringData.getData("Etc.img").getChildByPath("Etc"); for (MapleData itemFolder : itemsData.getChildren()) { entries.add(getItemNameEntry(itemFolder)); } itemsData = stringData.getData("Ins.img"); for (MapleData itemFolder : itemsData.getChildren()) { entries.add(getItemNameEntry(itemFolder)); } itemsData = stringData.getData("Pet.img"); for (MapleData itemFolder : itemsData.getChildren()) { entries.add(getItemNameEntry(itemFolder)); } return entries; } private static ItemNameEntry getItemNameEntry(MapleData itemFolder) { return new ItemNameEntry(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")); } private MapleData getStringData(int itemId) { String cat = "null"; MapleData theData; if (itemId >= 5010000) { theData = cashStringData; } else if (itemId >= 2000000 && itemId < 3000000) { theData = consumeStringData; } else if ((itemId >= 1010000 && itemId < 1040000) || (itemId >= 1122000 && itemId < 1123000) || (itemId >= 1142000 && itemId < 1143000)) { theData = eqpStringData; cat = "Eqp/Accessory"; } else if (itemId >= 1000000 && itemId < 1010000) { theData = eqpStringData; cat = "Eqp/Cap"; } else if (itemId >= 1102000 && itemId < 1103000) { theData = eqpStringData; cat = "Eqp/Cape"; } else if (itemId >= 1040000 && itemId < 1050000) { theData = eqpStringData; cat = "Eqp/Coat"; } else if (itemId >= 20000 && itemId < 22000) { theData = eqpStringData; cat = "Eqp/Face"; } else if (itemId >= 1080000 && itemId < 1090000) { theData = eqpStringData; cat = "Eqp/Glove"; } else if (itemId >= 30000 && itemId < 32000) { theData = eqpStringData; cat = "Eqp/Hair"; } else if (itemId >= 1050000 && itemId < 1060000) { theData = eqpStringData; cat = "Eqp/Longcoat"; } else if (itemId >= 1060000 && itemId < 1070000) { theData = eqpStringData; cat = "Eqp/Pants"; } else if (itemId >= 1802000 && itemId < 1810000) { theData = eqpStringData; cat = "Eqp/PetEquip"; } else if (itemId >= 1112000 && itemId < 1120000) { theData = eqpStringData; cat = "Eqp/Ring"; } else if (itemId >= 1092000 && itemId < 1100000) { theData = eqpStringData; cat = "Eqp/Shield"; } else if (itemId >= 1070000 && itemId < 1080000) { theData = eqpStringData; cat = "Eqp/Shoes"; } else if (itemId >= 1900000 && itemId < 2000000) { theData = eqpStringData; cat = "Eqp/Taming"; } else if (itemId >= 1300000 && itemId < 1800000) { theData = eqpStringData; cat = "Eqp/Weapon"; } else if (itemId >= 4000000 && itemId < 5000000) { theData = etcStringData; } else if (itemId >= 3000000 && itemId < 4000000) { theData = insStringData; } else if (itemId >= 5000000 && itemId < 5010000) { theData = petStringData; } else { return null; } if (cat.equalsIgnoreCase("null")) { return theData.getChildByPath(String.valueOf(itemId)); } else { return theData.getChildByPath(cat + "/" + itemId); } } public boolean noCancelMouse(int itemId) { MapleData item = getItemData(itemId); if (item == null) return false; return MapleDataTool.getIntConvert("info/noCancelMouse", item, 0) == 1; } private MapleData getItemData(int itemId) { MapleData ret = null; String idStr = "0" + String.valueOf(itemId); MapleDataDirectoryEntry root = itemData.getRoot(); for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) { for (MapleDataFileEntry iFile : topDir.getFiles()) { if (iFile.getName().equals(idStr.substring(0, 4) + ".img")) { ret = itemData.getData(topDir.getName() + "/" + iFile.getName()); if (ret == null) { return null; } ret = ret.getChildByPath(idStr); return ret; } else if (iFile.getName().equals(idStr.substring(1) + ".img")) { return itemData.getData(topDir.getName() + "/" + iFile.getName()); } } } root = equipData.getRoot(); for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) { for (MapleDataFileEntry iFile : topDir.getFiles()) { if (iFile.getName().equals(idStr + ".img")) { return equipData.getData(topDir.getName() + "/" + iFile.getName()); } } } return ret; } public short getSlotMax(MapleClient c, int itemId) { if (slotMaxCache.containsKey(itemId)) { return slotMaxCache.get(itemId); } short ret = 0; MapleData item = getItemData(itemId); if (item != null) { MapleData smEntry = item.getChildByPath("info/slotMax"); if (smEntry == null) { if (getInventoryType(itemId).getType() == MapleInventoryType.EQUIP.getType()) { ret = 1; } else { ret = 100; } } else { if (ItemConstants.isRechargable(itemId) || (MapleDataTool.getInt(smEntry) == 0)) { ret = 1; } ret = (short) MapleDataTool.getInt(smEntry); if (ItemConstants.isThrowingStar(itemId)) { ret += c.getPlayer().getSkillLevel(SkillFactory.getSkill(4100000)) * 10; } else { ret += c.getPlayer().getSkillLevel(SkillFactory.getSkill(5200000)) * 10; } } } if (!ItemConstants.isRechargable(itemId)) { slotMaxCache.put(itemId, ret); } return ret; } public int getMeso(int itemId) { if (getMesoCache.containsKey(itemId)) { return getMesoCache.get(itemId); } MapleData item = getItemData(itemId); if (item == null) { return -1; } int pEntry = 0; MapleData pData = item.getChildByPath("info/meso"); if (pData == null) { return -1; } pEntry = MapleDataTool.getInt(pData); getMesoCache.put(itemId, pEntry); return pEntry; } public int getWholePrice(int itemId) { if (wholePriceCache.containsKey(itemId)) { return wholePriceCache.get(itemId); } MapleData item = getItemData(itemId); if (item == null) { return -1; } int pEntry = 0; MapleData pData = item.getChildByPath("info/price"); if (pData == null) { return -1; } pEntry = MapleDataTool.getInt(pData); wholePriceCache.put(itemId, pEntry); return pEntry; } public double getPrice(int itemId) { if (priceCache.containsKey(itemId)) { return priceCache.get(itemId); } MapleData item = getItemData(itemId); if (item == null) { return -1; } double pEntry = 0.0; MapleData pData = item.getChildByPath("info/unitPrice"); if (pData != null) { try { pEntry = MapleDataTool.getDouble(pData); } catch (Exception e) { pEntry = (double) MapleDataTool.getInt(pData); } } else { pData = item.getChildByPath("info/price"); if (pData == null) { return -1; } pEntry = (double) MapleDataTool.getInt(pData); } priceCache.put(itemId, pEntry); return pEntry; } protected Map<String, Integer> getEquipStats(int itemId) { if (equipStatsCache.containsKey(itemId)) { return equipStatsCache.get(itemId); } Map<String, Integer> ret = new LinkedHashMap<String, Integer>(); MapleData item = getItemData(itemId); if (item == null) { return null; } MapleData info = item.getChildByPath("info"); if (info == null) { return null; } for (MapleData data : info.getChildren()) { if (data.getName().startsWith("inc")) ret.put(data.getName().substring(3), MapleDataTool.getIntConvert(data)); /* * else if (data.getName().startsWith("req")) * ret.put(data.getName(), MapleDataTool.getInt(data.getName(), * info, 0)); */ } ret.put("reqJob", MapleDataTool.getInt("reqJob", info, 0)); ret.put("reqLevel", MapleDataTool.getInt("reqLevel", info, 0)); ret.put("reqDEX", MapleDataTool.getInt("reqDEX", info, 0)); ret.put("reqSTR", MapleDataTool.getInt("reqSTR", info, 0)); ret.put("reqINT", MapleDataTool.getInt("reqINT", info, 0)); ret.put("reqLUK", MapleDataTool.getInt("reqLUK", info, 0)); ret.put("reqPOP", MapleDataTool.getInt("reqPOP", info, 0)); ret.put("cash", MapleDataTool.getInt("cash", info, 0)); ret.put("tuc", MapleDataTool.getInt("tuc", info, 0)); ret.put("cursed", MapleDataTool.getInt("cursed", info, 0)); ret.put("success", MapleDataTool.getInt("success", info, 0)); ret.put("fs", MapleDataTool.getInt("fs", info, 0)); equipStatsCache.put(itemId, ret); return ret; } public List<Integer> getScrollReqs(int itemId) { List<Integer> ret = new ArrayList<Integer>(); MapleData data = getItemData(itemId); data = data.getChildByPath("req"); if (data == null) { return ret; } for (MapleData req : data.getChildren()) { ret.add(MapleDataTool.getInt(req)); } return ret; } public MapleWeaponType getWeaponType(int itemId) { int cat = (itemId / 10000) % 100; MapleWeaponType[] type = {MapleWeaponType.SWORD1H, MapleWeaponType.AXE1H, MapleWeaponType.BLUNT1H, MapleWeaponType.DAGGER, MapleWeaponType.NOT_A_WEAPON, MapleWeaponType.NOT_A_WEAPON, MapleWeaponType.NOT_A_WEAPON, MapleWeaponType.WAND, MapleWeaponType.STAFF, MapleWeaponType.NOT_A_WEAPON, MapleWeaponType.SWORD2H, MapleWeaponType.AXE2H, MapleWeaponType.BLUNT2H, MapleWeaponType.SPEAR, MapleWeaponType.POLE_ARM, MapleWeaponType.BOW, MapleWeaponType.CROSSBOW, MapleWeaponType.CLAW, MapleWeaponType.KNUCKLE, MapleWeaponType.GUN}; if (cat < 30 || cat > 49) { return MapleWeaponType.NOT_A_WEAPON; } return type[cat - 30]; } private boolean isCleanSlate(int scrollId) { return scrollId > 2048999 && scrollId < 2049004; } public IItem scrollEquipWithId(IItem equip, int scrollId, boolean usingWhiteScroll, boolean isGM) { if (equip instanceof Equip) { Equip nEquip = (Equip) equip; Map<String, Integer> stats = this.getEquipStats(scrollId); Map<String, Integer> eqstats = this.getEquipStats(equip.getItemId()); if (((nEquip.getUpgradeSlots() > 0 || isCleanSlate(scrollId)) && Math.ceil(Math.random() * 100.0) <= stats.get("success")) || isGM) { short flag = nEquip.getFlag(); switch (scrollId) { case 2040727: flag |= ItemConstants.SPIKES; nEquip.setFlag((byte) flag); return equip; case 2041058: flag |= ItemConstants.COLD; nEquip.setFlag((byte) flag); return equip; case 2049000: case 2049001: case 2049002: case 2049003: if (nEquip.getLevel() + nEquip.getUpgradeSlots() < eqstats.get("tuc")) { nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() + 1)); } break; case 2049100: case 2049101: case 2049102: int inc = 1; if (Randomizer.nextInt(2) == 0) { inc = -1; } if (nEquip.getStr() > 0) { nEquip.setStr((short) Math.max(0, (nEquip.getStr() + Randomizer.nextInt(6) * inc))); } if (nEquip.getDex() > 0) { nEquip.setDex((short) Math.max(0, (nEquip.getDex() + Randomizer.nextInt(6) * inc))); } if (nEquip.getInt() > 0) { nEquip.setInt((short) Math.max(0, (nEquip.getInt() + Randomizer.nextInt(6) * inc))); } if (nEquip.getLuk() > 0) { nEquip.setLuk((short) Math.max(0, (nEquip.getLuk() + Randomizer.nextInt(6) * inc))); } if (nEquip.getWatk() > 0) { nEquip.setWatk((short) Math.max(0, (nEquip.getWatk() + Randomizer.nextInt(6) * inc))); } if (nEquip.getWdef() > 0) { nEquip.setWdef((short) Math.max(0, (nEquip.getWdef() + Randomizer.nextInt(6) * inc))); } if (nEquip.getMatk() > 0) { nEquip.setMatk((short) Math.max(0, (nEquip.getMatk() + Randomizer.nextInt(6) * inc))); } if (nEquip.getMdef() > 0) { nEquip.setMdef((short) Math.max(0, (nEquip.getMdef() + Randomizer.nextInt(6) * inc))); } if (nEquip.getAcc() > 0) { nEquip.setAcc((short) Math.max(0, (nEquip.getAcc() + Randomizer.nextInt(6) * inc))); } if (nEquip.getAvoid() > 0) { nEquip.setAvoid((short) Math.max(0, (nEquip.getAvoid() + Randomizer.nextInt(6) * inc))); } if (nEquip.getSpeed() > 0) { nEquip.setSpeed((short) Math.max(0, (nEquip.getSpeed() + Randomizer.nextInt(6) * inc))); } if (nEquip.getJump() > 0) { nEquip.setJump((short) Math.max(0, (nEquip.getJump() + Randomizer.nextInt(6) * inc))); } if (nEquip.getHp() > 0) { nEquip.setHp((short) Math.max(0, (nEquip.getHp() + Randomizer.nextInt(6) * inc))); } if (nEquip.getMp() > 0) { nEquip.setMp((short) Math.max(0, (nEquip.getMp() + Randomizer.nextInt(6) * inc))); } break; default: for (Entry<String, Integer> stat : stats.entrySet()) { if (stat.getKey().equals("STR")) { nEquip.setStr((short) (nEquip.getStr() + stat.getValue().intValue())); } else if (stat.getKey().equals("DEX")) { nEquip.setDex((short) (nEquip.getDex() + stat.getValue().intValue())); } else if (stat.getKey().equals("INT")) { nEquip.setInt((short) (nEquip.getInt() + stat.getValue().intValue())); } else if (stat.getKey().equals("LUK")) { nEquip.setLuk((short) (nEquip.getLuk() + stat.getValue().intValue())); } else if (stat.getKey().equals("PAD")) { nEquip.setWatk((short) (nEquip.getWatk() + stat.getValue().intValue())); } else if (stat.getKey().equals("PDD")) { nEquip.setWdef((short) (nEquip.getWdef() + stat.getValue().intValue())); } else if (stat.getKey().equals("MAD")) { nEquip.setMatk((short) (nEquip.getMatk() + stat.getValue().intValue())); } else if (stat.getKey().equals("MDD")) { nEquip.setMdef((short) (nEquip.getMdef() + stat.getValue().intValue())); } else if (stat.getKey().equals("ACC")) { nEquip.setAcc((short) (nEquip.getAcc() + stat.getValue().intValue())); } else if (stat.getKey().equals("EVA")) { nEquip.setAvoid((short) (nEquip.getAvoid() + stat.getValue().intValue())); } else if (stat.getKey().equals("Speed")) { nEquip.setSpeed((short) (nEquip.getSpeed() + stat.getValue().intValue())); } else if (stat.getKey().equals("Jump")) { nEquip.setJump((short) (nEquip.getJump() + stat.getValue().intValue())); } else if (stat.getKey().equals("MHP")) { nEquip.setHp((short) (nEquip.getHp() + stat.getValue().intValue())); } else if (stat.getKey().equals("MMP")) { nEquip.setMp((short) (nEquip.getMp() + stat.getValue().intValue())); } else if (stat.getKey().equals("afterImage")) { } } break; } if (!isCleanSlate(scrollId)) { if (!isGM) { nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1)); } nEquip.setLevel((byte) (nEquip.getLevel() + 1)); } } else { if (!usingWhiteScroll && !isCleanSlate(scrollId) && !isGM) { nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1)); } if (Randomizer.nextInt(101) < stats.get("cursed")) { return null; } } } return equip; } public IItem getEquipById(int equipId) { return getEquipById(equipId, -1); } IItem getEquipById(int equipId, int ringId) { Equip nEquip; nEquip = new Equip(equipId, (byte) 0, ringId); nEquip.setQuantity((short) 1); Map<String, Integer> stats = this.getEquipStats(equipId); if (stats != null) { for (Entry<String, Integer> stat : stats.entrySet()) { if (stat.getKey().equals("STR")) { nEquip.setStr((short) stat.getValue().intValue()); } else if (stat.getKey().equals("DEX")) { nEquip.setDex((short) stat.getValue().intValue()); } else if (stat.getKey().equals("INT")) { nEquip.setInt((short) stat.getValue().intValue()); } else if (stat.getKey().equals("LUK")) { nEquip.setLuk((short) stat.getValue().intValue()); } else if (stat.getKey().equals("PAD")) { nEquip.setWatk((short) stat.getValue().intValue()); } else if (stat.getKey().equals("PDD")) { nEquip.setWdef((short) stat.getValue().intValue()); } else if (stat.getKey().equals("MAD")) { nEquip.setMatk((short) stat.getValue().intValue()); } else if (stat.getKey().equals("MDD")) { nEquip.setMdef((short) stat.getValue().intValue()); } else if (stat.getKey().equals("ACC")) { nEquip.setAcc((short) stat.getValue().intValue()); } else if (stat.getKey().equals("EVA")) { nEquip.setAvoid((short) stat.getValue().intValue()); } else if (stat.getKey().equals("Speed")) { nEquip.setSpeed((short) stat.getValue().intValue()); } else if (stat.getKey().equals("Jump")) { nEquip.setJump((short) stat.getValue().intValue()); } else if (stat.getKey().equals("MHP")) { nEquip.setHp((short) stat.getValue().intValue()); } else if (stat.getKey().equals("MMP")) { nEquip.setMp((short) stat.getValue().intValue()); } else if (stat.getKey().equals("tuc")) { nEquip.setUpgradeSlots((byte) stat.getValue().intValue()); } else if (isDropRestricted(equipId)) { byte flag = nEquip.getFlag(); flag |= ItemConstants.UNTRADEABLE; nEquip.setFlag(flag); } else if (stats.get("fs") > 0) { byte flag = nEquip.getFlag(); flag |= ItemConstants.SPIKES; nEquip.setFlag(flag); equipCache.put(equipId, nEquip); } } } return nEquip.copy(); } private static short getRandStat(short defaultValue, int maxRange) { if (defaultValue == 0) { return 0; } int lMaxRange = (int) Math.min(Math.ceil(defaultValue * 0.1), maxRange); return (short) ((defaultValue - lMaxRange) + Math.floor(Randomizer.nextDouble() * (lMaxRange * 2 + 1))); } public Equip randomizeStats(Equip equip) { equip.setStr(getRandStat(equip.getStr(), 5)); equip.setDex(getRandStat(equip.getDex(), 5)); equip.setInt(getRandStat(equip.getInt(), 5)); equip.setLuk(getRandStat(equip.getLuk(), 5)); equip.setMatk(getRandStat(equip.getMatk(), 5)); equip.setWatk(getRandStat(equip.getWatk(), 5)); equip.setAcc(getRandStat(equip.getAcc(), 5)); equip.setAvoid(getRandStat(equip.getAvoid(), 5)); equip.setJump(getRandStat(equip.getJump(), 5)); equip.setSpeed(getRandStat(equip.getSpeed(), 5)); equip.setWdef(getRandStat(equip.getWdef(), 10)); equip.setMdef(getRandStat(equip.getMdef(), 10)); equip.setHp(getRandStat(equip.getHp(), 10)); equip.setMp(getRandStat(equip.getMp(), 10)); return equip; } public MapleStatEffect getItemEffect(int itemId) { MapleStatEffect ret = itemEffects.get(Integer.valueOf(itemId)); if (ret == null) { MapleData item = getItemData(itemId); if (item == null) { return null; } MapleData spec = item.getChildByPath("spec"); ret = MapleStatEffect.loadItemEffectFromData(spec, itemId); itemEffects.put(Integer.valueOf(itemId), ret); } return ret; } public int[][] getSummonMobs(int itemId) { MapleData data = getItemData(itemId); int theInt = data.getChildByPath("mob").getChildren().size(); int[][] mobs2spawn = new int[theInt][2]; for (int x = 0; x < theInt; x++) { mobs2spawn[x][0] = MapleDataTool.getIntConvert("mob/" + x + "/id", data); mobs2spawn[x][1] = MapleDataTool.getIntConvert("mob/" + x + "/prob", data); } return mobs2spawn; } public int getWatkForProjectile(int itemId) { Integer atk = projectileWatkCache.get(itemId); if (atk != null) { return atk.intValue(); } MapleData data = getItemData(itemId); atk = Integer.valueOf(MapleDataTool.getInt("info/incPAD", data, 0)); projectileWatkCache.put(itemId, atk); return atk.intValue(); } public String getName(int itemId) { if (nameCache.containsKey(itemId)) { return nameCache.get(itemId); } MapleData strings = getStringData(itemId); if (strings == null) { return null; } String ret = MapleDataTool.getString("name", strings, null); nameCache.put(itemId, ret); return ret; } public String getMsg(int itemId) { if (msgCache.containsKey(itemId)) { return msgCache.get(itemId); } MapleData strings = getStringData(itemId); if (strings == null) { return null; } String ret = MapleDataTool.getString("msg", strings, null); msgCache.put(itemId, ret); return ret; } public boolean isDropRestricted(int itemId) { if (dropRestrictionCache.containsKey(itemId)) { return dropRestrictionCache.get(itemId); } MapleData data = getItemData(itemId); boolean bRestricted = MapleDataTool.getIntConvert("info/tradeBlock", data, 0) == 1; if (!bRestricted) bRestricted = MapleDataTool.getIntConvert("info/quest", data, 0) == 1; dropRestrictionCache.put(itemId, bRestricted); return bRestricted; } public boolean isPickupRestricted(int itemId) { if (pickupRestrictionCache.containsKey(itemId)) { return pickupRestrictionCache.get(itemId); } MapleData data = getItemData(itemId); boolean bRestricted = MapleDataTool.getIntConvert("info/only", data, 0) == 1; pickupRestrictionCache.put(itemId, bRestricted); return bRestricted; } public Map<String, Integer> getSkillStats(int itemId, double playerJob) { Map<String, Integer> ret = new LinkedHashMap<String, Integer>(); MapleData item = getItemData(itemId); if (item == null) { return null; } MapleData info = item.getChildByPath("info"); if (info == null) { return null; } for (MapleData data : info.getChildren()) { if (data.getName().startsWith("inc")) { ret.put(data.getName().substring(3), MapleDataTool.getIntConvert(data)); } } ret.put("masterLevel", MapleDataTool.getInt("masterLevel", info, 0)); ret.put("reqSkillLevel", MapleDataTool.getInt("reqSkillLevel", info, 0)); ret.put("success", MapleDataTool.getInt("success", info, 0)); MapleData skill = info.getChildByPath("skill"); int curskill = 1; for (int i = 0; i < skill.getChildren().size(); i++) { curskill = MapleDataTool.getInt(Integer.toString(i), skill, 0); if (curskill == 0) { break; } if (curskill / 10000 == playerJob) { ret.put("skillid", curskill); break; } } if (ret.get("skillid") == null) { ret.put("skillid", 0); } return ret; } public List<Integer> petsCanConsume(int itemId) { List<Integer> ret = new ArrayList<Integer>(); MapleData data = getItemData(itemId); int curPetId = 0; for (int i = 0; i < data.getChildren().size(); i++) { curPetId = MapleDataTool.getInt("spec/" + Integer.toString(i), data, 0); if (curPetId == 0) { break; } ret.add(Integer.valueOf(curPetId)); } return ret; } public boolean isQuestItem(int itemId) { if (isQuestItemCache.containsKey(itemId)) { return isQuestItemCache.get(itemId); } MapleData data = getItemData(itemId); boolean questItem = MapleDataTool.getIntConvert("info/quest", data, 0) == 1; isQuestItemCache.put(itemId, questItem); return questItem; } public int getQuestIdFromItem(int itemId) { MapleData data = getItemData(itemId); int questItem = MapleDataTool.getIntConvert("info/quest", data, 0); return questItem; } private void loadCardIdData() { PreparedStatement ps = null; ResultSet rs = null; try { ps = DatabaseConnection.getConnection().prepareStatement("SELECT cardid, mobid FROM monstercarddata"); rs = ps.executeQuery(); while (rs.next()) { monsterBookID.put(rs.getInt(1), rs.getInt(2)); } rs.close(); ps.close(); } catch (SQLException e) { } finally { try { if (rs != null) { rs.close(); } if (ps != null) { ps.close(); } } catch (SQLException e) { } } } public int getCardMobId(int id) { return monsterBookID.get(id); } public boolean isUntradeableOnEquip(int itemId) { if (onEquipUntradableCache.containsKey(itemId)) { return onEquipUntradableCache.get(itemId); } boolean untradableOnEquip = MapleDataTool.getIntConvert("info/equipTradeBlock", getItemData(itemId), 0) > 0; onEquipUntradableCache.put(itemId, untradableOnEquip); return untradableOnEquip; } public scriptedItem getScriptedItemInfo(int itemId) { if (scriptedItemCache.containsKey(itemId)) { return scriptedItemCache.get(itemId); } if ((itemId / 10000) != 243) { return null; } scriptedItem script = new scriptedItem(MapleDataTool.getInt("spec/npc", getItemData(itemId), 0), MapleDataTool.getString("spec/script", getItemData(itemId), ""), MapleDataTool.getInt("spec/runOnPickup", getItemData(itemId), 0) == 1); scriptedItemCache.put(itemId, script); return scriptedItemCache.get(itemId); } public boolean isKarmaAble(int itemId) { if (karmaCache.containsKey(itemId)) { return karmaCache.get(itemId); } boolean bRestricted = MapleDataTool.getIntConvert("info/tradeAvailable", getItemData(itemId), 0) > 0; karmaCache.put(itemId, bRestricted); return bRestricted; } public int getStateChangeItem(int itemId) { if (triggerItemCache.containsKey(itemId)) { return triggerItemCache.get(itemId); } else { int triggerItem = MapleDataTool.getIntConvert("info/stateChangeItem", getItemData(itemId), 0); triggerItemCache.put(itemId, triggerItem); return triggerItem; } } public int getExpById(int itemId) { if (expCache.containsKey(itemId)) { return expCache.get(itemId); } else { int exp = MapleDataTool.getIntConvert("spec/exp", getItemData(itemId), 0); expCache.put(itemId, exp); return exp; } } public int getMaxLevelById(int itemId) { if (levelCache.containsKey(itemId)) { return levelCache.get(itemId); } else { int level = MapleDataTool.getIntConvert("info/maxLevel", getItemData(itemId), 256); levelCache.put(itemId, level); return level; } } public Pair<Integer, List<RewardItem>> getItemReward(int itemId) {// Thanks // Celino, // used // some // stuffs // :) if (rewardCache.containsKey(itemId)) { return rewardCache.get(itemId); } int totalprob = 0; List<RewardItem> rewards = new ArrayList<RewardItem>(); for (MapleData child : getItemData(itemId).getChildByPath("reward").getChildren()) { RewardItem reward = new RewardItem(); reward.itemid = MapleDataTool.getInt("item", child, 0); reward.prob = (byte) MapleDataTool.getInt("prob", child, 0); reward.quantity = (short) MapleDataTool.getInt("count", child, 0); reward.effect = MapleDataTool.getString("Effect", child, ""); reward.worldmsg = MapleDataTool.getString("worldMsg", child, null); reward.period = MapleDataTool.getInt("period", child, -1); totalprob += reward.prob; rewards.add(reward); } Pair<Integer, List<RewardItem>> hmm = new Pair<Integer, List<RewardItem>>(totalprob, rewards); rewardCache.put(itemId, hmm); return hmm; } public boolean isConsumeOnPickup(int itemId) { if (consumeOnPickupCache.containsKey(itemId)) { return consumeOnPickupCache.get(itemId); } MapleData data = getItemData(itemId); boolean consume = MapleDataTool.getIntConvert("spec/consumeOnPickup", data, 0) == 1 || MapleDataTool.getIntConvert("specEx/consumeOnPickup", data, 0) == 1; consumeOnPickupCache.put(itemId, consume); return consume; } public final boolean isTwoHanded(int itemId) { switch (getWeaponType(itemId)) { case AXE2H: case BLUNT2H: case BOW: case CLAW: case CROSSBOW: case POLE_ARM: case SPEAR: case SWORD2H: case GUN: case KNUCKLE: return true; default: return false; } } public boolean isCash(int itemId) { return itemId / 1000000 == 5 || getEquipStats(itemId).get("cash") == 1; } public Collection<IItem> canWearEquipment(MapleCharacter chr, Collection<IItem> items) { MapleInventory inv = chr.getInventory(MapleInventoryType.EQUIPPED); if (inv.checked()) return items; Collection<IItem> itemz = new LinkedList<IItem>(); if (chr.getJob() == MapleJob.SUPERGM || chr.getJob() == MapleJob.GM) { for (IItem item : items) { IEquip equip = (IEquip) item; equip.wear(true); itemz.add(item); } return itemz; } boolean highfivestamp = false; /* * Removed because players shouldn't even get this, and gm's should just * be gm job. try { for (Pair<IItem, MapleInventoryType> ii : * ItemFactory.INVENTORY.loadItems(chr.getId(), false)) { if * (ii.getRight() == MapleInventoryType.CASH) { if * (ii.getLeft().getItemId() == 5590000) { highfivestamp = true; } } } } * catch (SQLException ex) { } */ int tdex = chr.getDex(), tstr = chr.getStr(), tint = chr.getInt(), tluk = chr.getLuk(), fame = chr.getFame(); if (chr.getJob() != MapleJob.SUPERGM || chr.getJob() != MapleJob.GM) { for (IItem item : inv.list()) { IEquip equip = (IEquip) item; tdex += equip.getDex(); tstr += equip.getStr(); tluk += equip.getLuk(); tint += equip.getInt(); } } for (IItem item : items) { IEquip equip = (IEquip) item; int reqLevel = getEquipStats(equip.getItemId()).get("reqLevel"); if (highfivestamp) { reqLevel -= 5; if (reqLevel < 0) reqLevel = 0; } /* * int reqJob = getEquipStats(equip.getItemId()).get("reqJob"); if * (reqJob != 0) { Really hard check, and not really needed in this * one Gm's should just be GM job, and players cannot change jobs. } */ if (reqLevel > chr.getLevel()) continue; else if (getEquipStats(equip.getItemId()).get("reqDEX") > tdex) continue; else if (getEquipStats(equip.getItemId()).get("reqSTR") > tstr) continue; else if (getEquipStats(equip.getItemId()).get("reqLUK") > tluk) continue; else if (getEquipStats(equip.getItemId()).get("reqINT") > tint) continue; int reqPOP = getEquipStats(equip.getItemId()).get("reqPOP"); if (reqPOP > 0) { if (getEquipStats(equip.getItemId()).get("reqPOP") > fame) continue; } equip.wear(true); itemz.add(equip); } inv.checked(true); return itemz; } public boolean canWearEquipment(MapleCharacter chr, Equip equip) { if (chr.getJob() == MapleJob.SUPERGM || chr.getJob() == MapleJob.GM) { equip.wear(true); return true; } boolean highfivestamp = false; /* * Removed check above for message >< try { for (Pair<IItem, * MapleInventoryType> ii : ItemFactory.INVENTORY.loadItems(chr.getId(), * false)) { if (ii.getRight() == MapleInventoryType.CASH) { if * (ii.getLeft().getItemId() == 5590000) { highfivestamp = true; } } } } * catch (SQLException ex) { } */ int tdex = chr.getDex(), tstr = chr.getStr(), tint = chr.getInt(), tluk = chr.getLuk(); for (IItem item : chr.getInventory(MapleInventoryType.EQUIPPED).list()) { IEquip eq = (IEquip) item; tdex += eq.getDex(); tstr += eq.getStr(); tluk += eq.getLuk(); tint += eq.getInt(); } int reqLevel = getEquipStats(equip.getItemId()).get("reqLevel"); if (highfivestamp) { reqLevel -= 5; } int i = 0; // lol xD // Removed job check. Shouldn't really be needed. if (reqLevel > chr.getLevel()) i++; else if (getEquipStats(equip.getItemId()).get("reqDEX") > tdex) i++; else if (getEquipStats(equip.getItemId()).get("reqSTR") > tstr) i++; else if (getEquipStats(equip.getItemId()).get("reqLUK") > tluk) i++; else if (getEquipStats(equip.getItemId()).get("reqINT") > tint) i++; int reqPOP = getEquipStats(equip.getItemId()).get("reqPOP"); if (reqPOP > 0) { if (getEquipStats(equip.getItemId()).get("reqPOP") > chr.getFame()) i++; } if (i > 0) { equip.wear(false); return false; } equip.wear(true); return true; } public List<EquipLevelUpStat> getItemLevelupStats(int itemId, int level, boolean timeless) { List<EquipLevelUpStat> list = new LinkedList<EquipLevelUpStat>(); MapleData data = getItemData(itemId); MapleData data1 = data.getChildByPath("info").getChildByPath("level"); /* * if ((timeless && level == 5) || (!timeless && level == 3)) { * MapleData skilldata = * data1.getChildByPath("case").getChildByPath("1") * .getChildByPath(timeless ? "6" : "4"); if (skilldata != null) { * List<MapleData> skills = * skilldata.getChildByPath("Skill").getChildren(); for (int i = 0; i < * skilldata.getChildByPath("Skill").getChildren().size(); i++) { * System. * out.println(MapleDataTool.getInt(skills.get(i).getChildByPath("id" * ))); if (Math.random() < 0.1) list.add(new Pair<String, * Integer>("Skill" + 0, * MapleDataTool.getInt(skills.get(i).getChildByPath("id")))); } } } */ if (data1 != null) { MapleData data2 = data1.getChildByPath("info").getChildByPath(Integer.toString(level)); if (data2 != null) { for (MapleData da : data2.getChildren()) { if (Math.random() < 0.9) { final String name = da.getName(); final int lowerBound = MapleDataTool.getInt(da); if (name.startsWith("incDEXMin")) { list.add(new EquipLevelUpStat("incDEX", Randomizer.rand(lowerBound, MapleDataTool.getInt("incDEXMax", data2)))); } else if (name.startsWith("incSTRMin")) { list.add(new EquipLevelUpStat("incSTR", Randomizer.rand(lowerBound, MapleDataTool.getInt("incSTRMax", data2)))); } else if (name.startsWith("incINTMin")) { list.add(new EquipLevelUpStat("incINT", Randomizer.rand(lowerBound, MapleDataTool.getInt("incINTMax", data2)))); } else if (name.startsWith("incLUKMin")) { list.add(new EquipLevelUpStat("incLUK", Randomizer.rand(lowerBound, MapleDataTool.getInt("incLUKMax", data2)))); } else if (name.startsWith("incMHPMin")) { list.add(new EquipLevelUpStat("incMHP", Randomizer.rand(lowerBound, MapleDataTool.getInt("incMHPMax", data2)))); } else if (name.startsWith("incMMPMin")) { list.add(new EquipLevelUpStat("incMMP", Randomizer.rand(lowerBound, MapleDataTool.getInt("incMMPMax", data2)))); } else if (name.startsWith("incPADMin")) { list.add(new EquipLevelUpStat("incPAD", Randomizer.rand(lowerBound, MapleDataTool.getInt("incPADMax", data2)))); } else if (name.startsWith("incMADMin")) { list.add(new EquipLevelUpStat("incMAD", Randomizer.rand(lowerBound, MapleDataTool.getInt("incMADMax", data2)))); } else if (name.startsWith("incPDDMin")) { list.add(new EquipLevelUpStat("incPDD", Randomizer.rand(lowerBound, MapleDataTool.getInt("incPDDMax", data2)))); } else if (name.startsWith("incMDDMin")) { list.add(new EquipLevelUpStat("incMDD", Randomizer.rand(lowerBound, MapleDataTool.getInt("incMDDMax", data2)))); } else if (name.startsWith("incACCMin")) { list.add(new EquipLevelUpStat("incACC", Randomizer.rand(lowerBound, MapleDataTool.getInt("incACCMax", data2)))); } else if (name.startsWith("incEVAMin")) { list.add(new EquipLevelUpStat("incEVA", Randomizer.rand(lowerBound, MapleDataTool.getInt("incEVAMax", data2)))); } else if (name.startsWith("incSpeedMin")) { list.add(new EquipLevelUpStat("incSpeed", Randomizer.rand(lowerBound, MapleDataTool.getInt("incSpeedMax", data2)))); } else if (name.startsWith("incJumpMin")) { list.add(new EquipLevelUpStat("incJump", Randomizer.rand(lowerBound, MapleDataTool.getInt("incJumpMax", data2)))); } } } } } return list; } public class scriptedItem { private boolean runOnPickup; private int npc; private String script; public scriptedItem(int npc, String script, boolean rop) { this.npc = npc; this.script = script; this.runOnPickup = rop; } public int getNpc() { return npc; } public String getScript() { return script; } public boolean runOnPickup() { return runOnPickup; } } public static final class RewardItem { public int itemid, period; public short prob, quantity; public String effect, worldmsg; } }