package javastory.game.data; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javastory.channel.server.StatEffect; import javastory.game.Equip; import javastory.game.GameConstants; import javastory.game.IdNameEntry; import javastory.game.IdProbabilityEntry; import javastory.game.InventoryType; import javastory.game.Item; import javastory.game.ItemConsumeType; import javastory.game.ItemFlag; import javastory.game.ItemType; import javastory.server.EquipLevelInfo; import javastory.tools.Randomizer; import javastory.wz.WzData; import javastory.wz.WzDataDirectoryEntry; import javastory.wz.WzDataFileEntry; import javastory.wz.WzDataProvider; import javastory.wz.WzDataProviderFactory; import javastory.wz.WzDataTool; import javastory.wz.WzDataType; import com.google.common.collect.Lists; import com.google.common.collect.Maps; public final class ItemInfoProvider { // private final static ItemInfoProvider instance = new ItemInfoProvider(); private final WzDataProvider itemData = WzDataProviderFactory.getDataProvider("Item.wz"); private final WzDataProvider equipData = WzDataProviderFactory.getDataProvider("Character.wz"); private final WzDataProvider stringData = WzDataProviderFactory.getDataProvider("String.wz"); private final WzData cashStringData = this.stringData.getData("Cash.img"); private final WzData consumeStringData = this.stringData.getData("Consume.img"); private final WzData eqpStringData = this.stringData.getData("Eqp.img"); private final WzData etcStringData = this.stringData.getData("Etc.img"); private final WzData insStringData = this.stringData.getData("Ins.img"); private final WzData petStringData = this.stringData.getData("Pet.img"); // private final Map<Integer, Short> slotMaxCache = Maps.newHashMap(); private final Map<Integer, StatEffect> itemEffects = Maps.newHashMap(); private final Map<Integer, Map<String, Integer>> equipStatsCache = Maps.newHashMap(); private final Map<Integer, Map<String, Byte>> itemMakeStatsCache = Maps.newHashMap(); private final Map<Integer, List<EquipLevelInfo>> equipLevelCache = Maps.newHashMap(); private final Map<Integer, Short> itemMakeLevel = Maps.newHashMap(); private final Map<Integer, Equip> equipCache = Maps.newHashMap(); private final Map<Integer, Double> priceCache = Maps.newHashMap(); private final Map<Integer, Integer> wholePriceCache = Maps.newHashMap(); private final Map<Integer, Integer> projectileWatkCache = Maps.newHashMap(); private final Map<Integer, Integer> monsterBookID = Maps.newHashMap(); private final Map<Integer, String> nameCache = Maps.newHashMap(); private final Map<Integer, String> descCache = Maps.newHashMap(); private final Map<Integer, String> msgCache = Maps.newHashMap(); private final Map<Integer, Map<String, Integer>> SkillStatsCache = Maps.newHashMap(); private final Map<Integer, ItemConsumeType> consumeOnPickupCache = Maps.newHashMap(); private final Map<Integer, Boolean> dropRestrictionCache = Maps.newHashMap(); private final Map<Integer, Boolean> pickupRestrictionCache = Maps.newHashMap(); private final Map<Integer, Integer> stateChangeCache = Maps.newHashMapWithExpectedSize(40); private final Map<Integer, Integer> karmaEnabledCache = Maps.newHashMap(); private final Map<Integer, Boolean> isQuestItemCache = Maps.newHashMap(); private final Map<Integer, List<IdProbabilityEntry>> summonMobCache = Maps.newHashMap(); private final List<IdNameEntry> itemNameCache = Lists.newArrayList(); private final Map<Integer, RewardSetInfo> RewardItem = Maps.newHashMap(); private ItemInfoProvider() { System.out.println(":: Loading MapleItemInformationProvider ::"); } public static ItemInfoProvider getInstance() { return instance; } public final List<IdNameEntry> getAllItems() { if (!this.itemNameCache.isEmpty()) { return this.itemNameCache; } final List<IdNameEntry> itemPairs = Lists.newArrayList(); WzData itemsData; itemsData = this.stringData.getData("Cash.img"); for (final WzData itemFolder : itemsData.getChildren()) { final IdNameEntry entry = new IdNameEntry(Integer.parseInt(itemFolder.getName()), WzDataTool.getString("name", itemFolder, "NO-NAME")); itemPairs.add(entry); } itemsData = this.stringData.getData("Consume.img"); for (final WzData itemFolder : itemsData.getChildren()) { final IdNameEntry entry = new IdNameEntry(Integer.parseInt(itemFolder.getName()), WzDataTool.getString("name", itemFolder, "NO-NAME")); itemPairs.add(entry); } itemsData = this.stringData.getData("Eqp.img").getChildByPath("Eqp"); for (final WzData eqpType : itemsData.getChildren()) { for (final WzData itemFolder : eqpType.getChildren()) { final IdNameEntry entry = new IdNameEntry(Integer.parseInt(itemFolder.getName()), WzDataTool.getString("name", itemFolder, "NO-NAME")); itemPairs.add(entry); } } itemsData = this.stringData.getData("Etc.img").getChildByPath("Etc"); for (final WzData itemFolder : itemsData.getChildren()) { final IdNameEntry entry = new IdNameEntry(Integer.parseInt(itemFolder.getName()), WzDataTool.getString("name", itemFolder, "NO-NAME")); itemPairs.add(entry); } itemsData = this.stringData.getData("Ins.img"); for (final WzData itemFolder : itemsData.getChildren()) { final IdNameEntry entry = new IdNameEntry(Integer.parseInt(itemFolder.getName()), WzDataTool.getString("name", itemFolder, "NO-NAME")); itemPairs.add(entry); } itemsData = this.stringData.getData("Pet.img"); for (final WzData itemFolder : itemsData.getChildren()) { final IdNameEntry entry = new IdNameEntry(Integer.parseInt(itemFolder.getName()), WzDataTool.getString("name", itemFolder, "NO-NAME")); itemPairs.add(entry); } return itemPairs; } private WzData getStringData(final int itemId) { String cat = null; WzData data; if (itemId >= 5010000) { data = this.cashStringData; } else if (itemId >= 2000000 && itemId < 3000000) { data = this.consumeStringData; } else if (itemId >= 1142000 && itemId < 1143000 || itemId >= 1010000 && itemId < 1040000 || itemId >= 1122000 && itemId < 1123000) { data = this.eqpStringData; cat = "Accessory"; } else if (itemId >= 1000000 && itemId < 1010000) { data = this.eqpStringData; cat = "Cap"; } else if (itemId >= 1102000 && itemId < 1103000) { data = this.eqpStringData; cat = "Cape"; } else if (itemId >= 1040000 && itemId < 1050000) { data = this.eqpStringData; cat = "Coat"; } else if (itemId >= 20000 && itemId < 22000) { data = this.eqpStringData; cat = "Face"; } else if (itemId >= 1080000 && itemId < 1090000) { data = this.eqpStringData; cat = "Glove"; } else if (itemId >= 30000 && itemId < 32000) { data = this.eqpStringData; cat = "Hair"; } else if (itemId >= 1050000 && itemId < 1060000) { data = this.eqpStringData; cat = "Longcoat"; } else if (itemId >= 1060000 && itemId < 1070000) { data = this.eqpStringData; cat = "Pants"; } else if (itemId >= 1802000 && itemId < 1810000) { data = this.eqpStringData; cat = "PetEquip"; } else if (itemId >= 1112000 && itemId < 1120000) { data = this.eqpStringData; cat = "Ring"; } else if (itemId >= 1092000 && itemId < 1100000) { data = this.eqpStringData; cat = "Shield"; } else if (itemId >= 1070000 && itemId < 1080000) { data = this.eqpStringData; cat = "Shoes"; } else if (itemId >= 1900000 && itemId < 2000000) { data = this.eqpStringData; cat = "Taming"; } else if (itemId >= 1300000 && itemId < 1800000) { data = this.eqpStringData; cat = "Weapon"; } else if (itemId >= 4000000 && itemId < 5000000) { data = this.etcStringData; } else if (itemId >= 3000000 && itemId < 4000000) { data = this.insStringData; } else if (itemId >= 5000000 && itemId < 5010000) { data = this.petStringData; } else { return null; } if (cat == null) { return data.getChildByPath(String.valueOf(itemId)); } else { return data.getChildByPath("Eqp/" + cat + "/" + itemId); } } private WzData getItemData(final int itemId) { WzData ret = null; final String idStr = "0" + String.valueOf(itemId); WzDataDirectoryEntry root = this.itemData.getRoot(); for (final WzDataDirectoryEntry topDir : root.getSubdirectories()) { // we should have .img files here beginning with the first 4 IID for (final WzDataFileEntry iFile : topDir.getFiles()) { if (iFile.getName().equals(idStr.substring(0, 4) + ".img")) { ret = this.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 this.itemData.getData(topDir.getName() + "/" + iFile.getName()); } } } root = this.equipData.getRoot(); for (final WzDataDirectoryEntry topDir : root.getSubdirectories()) { for (final WzDataFileEntry iFile : topDir.getFiles()) { if (iFile.getName().equals(idStr + ".img")) { return this.equipData.getData(topDir.getName() + "/" + iFile.getName()); } } } return ret; } /** returns the maximum of items in one slot */ public final short getSlotMax(final int itemId) { if (this.slotMaxCache.containsKey(itemId)) { return this.slotMaxCache.get(itemId); } short ret = 0; final WzData item = this.getItemData(itemId); if (item != null) { final WzData smEntry = item.getChildByPath("info/slotMax"); if (smEntry == null) { if (GameConstants.getInventoryType(itemId) == InventoryType.EQUIP) { ret = 1; } else { ret = 100; } } else { ret = (short) WzDataTool.getInt(smEntry); } } this.slotMaxCache.put(itemId, ret); return ret; } public final int getWholePrice(final int itemId) { if (this.wholePriceCache.containsKey(itemId)) { return this.wholePriceCache.get(itemId); } final WzData item = this.getItemData(itemId); if (item == null) { return -1; } int pEntry = 0; final WzData pData = item.getChildByPath("info/price"); if (pData == null) { return -1; } pEntry = WzDataTool.getInt(pData); this.wholePriceCache.put(itemId, pEntry); return pEntry; } public final double getPrice(final int itemId) { if (this.priceCache.containsKey(itemId)) { return this.priceCache.get(itemId); } final WzData item = this.getItemData(itemId); if (item == null) { return -1; } double pEntry = 0.0; WzData pData = item.getChildByPath("info/unitPrice"); if (pData != null) { if (pData.getType() == WzDataType.DOUBLE) { pEntry = WzDataTool.getDouble(pData); } else { pEntry = WzDataTool.getInt(pData); } } else { pData = item.getChildByPath("info/price"); if (pData == null) { return -1; } pEntry = WzDataTool.getInt(pData); } if (itemId == 2070019 || itemId == 2330007) { pEntry = 1.0; } this.priceCache.put(itemId, pEntry); return pEntry; } public final List<EquipLevelInfo> getEquipLevelStat(final int itemid, final byte level) { if (this.equipLevelCache.containsKey(itemid)) { return this.equipLevelCache.get(itemid); } final WzData item = this.getItemData(itemid); if (item == null) { return null; } final WzData info = item.getChildByPath("info/level"); if (info == null) { return null; } final List<EquipLevelInfo> el = Lists.newArrayList(); EquipLevelInfo sel; for (final WzData data : info.getChildByPath("info")) { sel = new EquipLevelInfo(); sel.incSTRMax = (byte) WzDataTool.getInt("incSTRMax", data, 0); sel.incSTRMin = (byte) WzDataTool.getInt("incSTRMin", data, 0); sel.incDEXMax = (byte) WzDataTool.getInt("incDEXMax", data, 0); sel.incDEXMin = (byte) WzDataTool.getInt("incDEXMin", data, 0); sel.incLUKMax = (byte) WzDataTool.getInt("incLUKMax", data, 0); sel.incLUKMin = (byte) WzDataTool.getInt("incLUKMin", data, 0); sel.incINTMax = (byte) WzDataTool.getInt("incINTMax", data, 0); sel.incINTMin = (byte) WzDataTool.getInt("incINTMin", data, 0); sel.incPADMax = (byte) WzDataTool.getInt("incPADMax", data, 0); sel.incPADMin = (byte) WzDataTool.getInt("incPADMin", data, 0); sel.incMADMax = (byte) WzDataTool.getInt("incMADMax", data, 0); sel.incMADMin = (byte) WzDataTool.getInt("incMADMin", data, 0); el.add(sel); } this.equipLevelCache.put(itemid, el); return el; } public final Map<String, Byte> getItemMakeStats(final int itemId) { if (this.itemMakeStatsCache.containsKey(itemId)) { return this.itemMakeStatsCache.get(itemId); } if (itemId / 10000 != 425) { return null; } final Map<String, Byte> ret = Maps.newLinkedHashMap(); final WzData item = this.getItemData(itemId); if (item == null) { return null; } final WzData info = item.getChildByPath("info"); if (info == null) { return null; } ret.put("incPAD", (byte) WzDataTool.getInt("incPAD", info, 0)); // WATK ret.put("incMAD", (byte) WzDataTool.getInt("incMAD", info, 0)); // MATK ret.put("incACC", (byte) WzDataTool.getInt("incACC", info, 0)); // ACC ret.put("incEVA", (byte) WzDataTool.getInt("incEVA", info, 0)); // AVOID ret.put("incSpeed", (byte) WzDataTool.getInt("incSpeed", info, 0)); // SPEED ret.put("incJump", (byte) WzDataTool.getInt("incJump", info, 0)); // JUMP ret.put("incMaxHP", (byte) WzDataTool.getInt("incMaxHP", info, 0)); // HP ret.put("incMaxMP", (byte) WzDataTool.getInt("incMaxMP", info, 0)); // MP ret.put("incSTR", (byte) WzDataTool.getInt("incSTR", info, 0)); // STR ret.put("incINT", (byte) WzDataTool.getInt("incINT", info, 0)); // INT ret.put("incLUK", (byte) WzDataTool.getInt("incLUK", info, 0)); // LUK ret.put("incDEX", (byte) WzDataTool.getInt("incDEX", info, 0)); // DEX // ret.put("incReqLevel", MapleDataTool.getInt("incReqLevel", info, 0)); // IDK! ret.put("randOption", (byte) WzDataTool.getInt("randOption", info, 0)); // Black Crystal Wa/MA ret.put("randStat", (byte) WzDataTool.getInt("randStat", info, 0)); // Dark Crystal - Str/Dex/int/Luk this.itemMakeStatsCache.put(itemId, ret); return ret; } public final Map<String, Integer> getEquipStats(final int itemId) { if (this.equipStatsCache.containsKey(itemId)) { return this.equipStatsCache.get(itemId); } final Map<String, Integer> ret = Maps.newLinkedHashMap(); final WzData item = this.getItemData(itemId); if (item == null) { return null; } final WzData info = item.getChildByPath("info"); if (info == null) { return null; } for (final WzData data : info.getChildren()) { if (data.getName().startsWith("inc")) { ret.put(data.getName().substring(3), WzDataTool.getIntConvert(data)); } } ret.put("tuc", WzDataTool.getInt("tuc", info, 0)); ret.put("reqLevel", WzDataTool.getInt("reqLevel", info, 0)); ret.put("reqJob", WzDataTool.getInt("reqJob", info, 0)); ret.put("reqSTR", WzDataTool.getInt("reqSTR", info, 0)); ret.put("reqDEX", WzDataTool.getInt("reqDEX", info, 0)); ret.put("reqINT", WzDataTool.getInt("reqINT", info, 0)); ret.put("reqLUK", WzDataTool.getInt("reqLUK", info, 0)); ret.put("reqPOP", WzDataTool.getInt("reqPOP", info, 0)); ret.put("cash", WzDataTool.getInt("cash", info, 0)); ret.put("canLevel", info.getChildByPath("level") == null ? 0 : 1); ret.put("cursed", WzDataTool.getInt("cursed", info, 0)); ret.put("success", WzDataTool.getInt("success", info, 0)); ret.put("equipTradeBlock", WzDataTool.getInt("equipTradeBlock", info, 0)); if (GameConstants.isMagicWeapon(itemId)) { ret.put("elemDefault", WzDataTool.getInt("elemDefault", info, 100)); ret.put("incRMAS", WzDataTool.getInt("incRMAS", info, 100)); // Poison ret.put("incRMAF", WzDataTool.getInt("incRMAF", info, 100)); // Fire ret.put("incRMAL", WzDataTool.getInt("incRMAL", info, 100)); // Lightning ret.put("incRMAI", WzDataTool.getInt("incRMAI", info, 100)); // Ice } this.equipStatsCache.put(itemId, ret); return ret; } public final boolean canEquip(final Map<String, Integer> stats, final int itemid, final int level, final int job, final int fame, final int str, final int dex, final int luk, final int int_) { if (level >= stats.get("reqLevel") && str >= stats.get("reqSTR") && dex >= stats.get("reqDEX") && luk >= stats.get("reqLUK") && int_ >= stats.get("reqINT")) { final int fameReq = stats.get("reqPOP"); if (fameReq != 0 && fame < fameReq) { return false; } return true; } return false; } public final int getReqLevel(final int itemId) { return this.getEquipStats(itemId).get("reqLevel"); } public final List<Integer> getScrollReqs(final int itemId) { final List<Integer> ret = Lists.newArrayList(); final WzData data = this.getItemData(itemId).getChildByPath("req"); if (data == null) { return ret; } for (final WzData req : data.getChildren()) { ret.add(WzDataTool.getInt(req)); } return ret; } public final Item scrollEquipWithId(final Item equipItem, final int scrollId, final boolean ws) { if (equipItem.getType() == ItemType.EQUIP) { final Equip equip = (Equip) equipItem; final Map<String, Integer> stats = this.getEquipStats(scrollId); final Map<String, Integer> eqstats = this.getEquipStats(equip.getItemId()); if (Randomizer.nextInt(100) <= stats.get("success")) { switch (scrollId) { case 2049000: case 2049001: case 2049002: case 2049003: { if (equip.getLevel() + equip.getUpgradeSlots() < eqstats.get("tuc")) { equip.setUpgradeSlots((byte) (equip.getUpgradeSlots() + 1)); } break; } case 2040727: // Spikes on shoe, prevents slip { byte flag = equip.getFlag(); flag |= ItemFlag.SPIKES.getValue(); equip.setFlag(flag); break; } case 2041058: // Cape for Cold protection { byte flag = equip.getFlag(); flag |= ItemFlag.COLD.getValue(); equip.setFlag(flag); break; } case 2049100: // Chaos Scroll case 2049101: // Liar's Wood Liquid case 2049102: // Maple Syrup case 2049104: // Angent Equipmenet scroll case 2049103: this.setRandomStats(equip); break; default: this.setDefaultStats(stats, equip); break; } if (!GameConstants.isCleanSlate(scrollId) && !GameConstants.isSpecialScroll(scrollId)) { equip.setUpgradeSlots((byte) (equip.getUpgradeSlots() - 1)); equip.setLevel((byte) (equip.getLevel() + 1)); } } else { if (!ws && !GameConstants.isCleanSlate(scrollId) && !GameConstants.isSpecialScroll(scrollId)) { equip.setUpgradeSlots((byte) (equip.getUpgradeSlots() - 1)); } if (Randomizer.nextInt(99) < stats.get("cursed")) { return null; } } } return equipItem; } private void setDefaultStats(final Map<String, Integer> stats, final Equip equip) { for (final Entry<String, Integer> stat : stats.entrySet()) { final String key = stat.getKey(); switch (key) { case "STR": equip.setStr((short) (equip.getStr() + stat.getValue().intValue())); break; case "DEX": equip.setDex((short) (equip.getDex() + stat.getValue().intValue())); break; case "INT": equip.setInt((short) (equip.getInt() + stat.getValue().intValue())); break; case "LUK": equip.setLuk((short) (equip.getLuk() + stat.getValue().intValue())); break; case "PAD": equip.setWatk((short) (equip.getWatk() + stat.getValue().intValue())); break; case "PDD": equip.setWdef((short) (equip.getWdef() + stat.getValue().intValue())); break; case "MAD": equip.setMatk((short) (equip.getMatk() + stat.getValue().intValue())); break; case "MDD": equip.setMdef((short) (equip.getMdef() + stat.getValue().intValue())); break; case "ACC": equip.setAcc((short) (equip.getAcc() + stat.getValue().intValue())); break; case "EVA": equip.setAvoid((short) (equip.getAvoid() + stat.getValue().intValue())); break; case "Speed": equip.setSpeed((short) (equip.getSpeed() + stat.getValue().intValue())); break; case "Jump": equip.setJump((short) (equip.getJump() + stat.getValue().intValue())); break; case "MHP": equip.setHp((short) (equip.getHp() + stat.getValue().intValue())); break; case "MMP": equip.setMp((short) (equip.getMp() + stat.getValue().intValue())); break; } } return; } private void setRandomStats(final Equip equip) { // Beach Sandals Scroll final int increase = Randomizer.nextBoolean() ? 1 : -1; if (equip.getStr() > 0) { equip.setStr((short) (equip.getStr() + Randomizer.nextInt(5) * increase)); } if (equip.getDex() > 0) { equip.setDex((short) (equip.getDex() + Randomizer.nextInt(5) * increase)); } if (equip.getInt() > 0) { equip.setInt((short) (equip.getInt() + Randomizer.nextInt(5) * increase)); } if (equip.getLuk() > 0) { equip.setLuk((short) (equip.getLuk() + Randomizer.nextInt(5) * increase)); } if (equip.getWatk() > 0) { equip.setWatk((short) (equip.getWatk() + Randomizer.nextInt(5) * increase)); } if (equip.getWdef() > 0) { equip.setWdef((short) (equip.getWdef() + Randomizer.nextInt(5) * increase)); } if (equip.getMatk() > 0) { equip.setMatk((short) (equip.getMatk() + Randomizer.nextInt(5) * increase)); } if (equip.getMdef() > 0) { equip.setMdef((short) (equip.getMdef() + Randomizer.nextInt(5) * increase)); } if (equip.getAcc() > 0) { equip.setAcc((short) (equip.getAcc() + Randomizer.nextInt(5) * increase)); } if (equip.getAvoid() > 0) { equip.setAvoid((short) (equip.getAvoid() + Randomizer.nextInt(5) * increase)); } if (equip.getSpeed() > 0) { equip.setSpeed((short) (equip.getSpeed() + Randomizer.nextInt(5) * increase)); } if (equip.getJump() > 0) { equip.setJump((short) (equip.getJump() + Randomizer.nextInt(5) * increase)); } if (equip.getHp() > 0) { equip.setHp((short) (equip.getHp() + Randomizer.nextInt(5) * increase)); } if (equip.getMp() > 0) { equip.setMp((short) (equip.getMp() + Randomizer.nextInt(5) * increase)); } } public final Item getEquipById(final int equipId) { return this.getEquipById(equipId, -1); } public final Item getEquipById(final int equipId, final int ringId) { final Equip nEquip = new Equip(equipId, (byte) 0, ringId, (byte) 0); nEquip.setQuantity((short) 1); final Map<String, Integer> stats = this.getEquipStats(equipId); if (stats != null) { for (final Entry<String, Integer> stat : stats.entrySet()) { final String key = stat.getKey(); final int statValue = stat.getValue().intValue(); switch (key) { case "STR": nEquip.setStr((short) statValue); break; case "DEX": nEquip.setDex((short) statValue); break; case "INT": nEquip.setInt((short) statValue); break; case "LUK": nEquip.setLuk((short) statValue); break; case "PAD": nEquip.setWatk((short) statValue); break; case "PDD": nEquip.setWdef((short) statValue); break; case "MAD": nEquip.setMatk((short) statValue); break; case "MDD": nEquip.setMdef((short) statValue); break; case "ACC": nEquip.setAcc((short) statValue); break; case "EVA": nEquip.setAvoid((short) statValue); break; case "Speed": nEquip.setSpeed((short) statValue); break; case "Jump": nEquip.setJump((short) statValue); break; case "MHP": nEquip.setHp((short) statValue); break; case "MMP": nEquip.setMp((short) statValue); break; case "tuc": nEquip.setUpgradeSlots((byte) statValue); break; case "Craft": nEquip.setHands((short) statValue); break; } } } this.equipCache.put(equipId, nEquip); return nEquip.copy(); } private short getRandStat(final short defaultValue, final int maxRange) { if (defaultValue == 0) { return 0; } // vary no more than ceil of 10% of stat final int lMaxRange = (int) Math.min(Math.ceil(defaultValue * 0.1), maxRange); return (short) (defaultValue - lMaxRange + Math.floor(Math.random() * (lMaxRange * 2 + 1))); } public final Equip randomizeStats(final Equip equip) { equip.setStr(this.getRandStat(equip.getStr(), 5)); equip.setDex(this.getRandStat(equip.getDex(), 5)); equip.setInt(this.getRandStat(equip.getInt(), 5)); equip.setLuk(this.getRandStat(equip.getLuk(), 5)); equip.setMatk(this.getRandStat(equip.getMatk(), 5)); equip.setWatk(this.getRandStat(equip.getWatk(), 5)); equip.setAcc(this.getRandStat(equip.getAcc(), 5)); equip.setAvoid(this.getRandStat(equip.getAvoid(), 5)); equip.setJump(this.getRandStat(equip.getJump(), 5)); equip.setHands(this.getRandStat(equip.getHands(), 5)); equip.setSpeed(this.getRandStat(equip.getSpeed(), 5)); equip.setWdef(this.getRandStat(equip.getWdef(), 10)); equip.setMdef(this.getRandStat(equip.getMdef(), 10)); equip.setHp(this.getRandStat(equip.getHp(), 10)); equip.setMp(this.getRandStat(equip.getMp(), 10)); return equip; } public final StatEffect getItemEffect(final int itemId) { StatEffect ret = this.itemEffects.get(Integer.valueOf(itemId)); if (ret == null) { final WzData item = this.getItemData(itemId); if (item == null) { return null; } ret = StatEffect.loadItemEffectFromData(item.getChildByPath("spec"), itemId); this.itemEffects.put(Integer.valueOf(itemId), ret); } return ret; } public final List<IdProbabilityEntry> getSummonMobs(final int itemId) { if (this.summonMobCache.containsKey(Integer.valueOf(itemId))) { return this.summonMobCache.get(itemId); } if (!GameConstants.isSummonSack(itemId)) { return null; } final WzData data = this.getItemData(itemId).getChildByPath("mob"); if (data == null) { return null; } final List<IdProbabilityEntry> entries = Lists.newArrayList(); for (final WzData child : data.getChildren()) { entries.add(new IdProbabilityEntry(WzDataTool.getIntConvert("id", child), WzDataTool.getIntConvert("prob", child))); } this.summonMobCache.put(itemId, entries); return entries; } public final int getCardMobId(final int id) { if (id == 0) { return 0; } if (this.monsterBookID.containsKey(id)) { return this.monsterBookID.get(id); } final WzData data = this.getItemData(id); final int monsterid = WzDataTool.getIntConvert("info/mob", data, 0); if (monsterid == 0) { // Hack. return 0; } this.monsterBookID.put(id, monsterid); return this.monsterBookID.get(id); } public final int getWatkForProjectile(final int itemId) { Integer atk = this.projectileWatkCache.get(itemId); if (atk != null) { return atk.intValue(); } final WzData data = this.getItemData(itemId); atk = Integer.valueOf(WzDataTool.getInt("info/incPAD", data, 0)); this.projectileWatkCache.put(itemId, atk); return atk.intValue(); } public final boolean canScroll(final int scrollId, final int itemId) { return scrollId / 100 % 100 == itemId / 10000 % 100; } public final String getName(final int itemId) { if (this.nameCache.containsKey(itemId)) { return this.nameCache.get(itemId); } final WzData strings = this.getStringData(itemId); if (strings == null) { return null; } final String ret = WzDataTool.getString("name", strings, null); this.nameCache.put(itemId, ret); return ret; } public final String getDesc(final int itemId) { if (this.descCache.containsKey(itemId)) { return this.descCache.get(itemId); } final WzData strings = this.getStringData(itemId); if (strings == null) { return null; } final String ret = WzDataTool.getString("desc", strings, null); this.descCache.put(itemId, ret); return ret; } public final String getMsg(final int itemId) { if (this.msgCache.containsKey(itemId)) { return this.msgCache.get(itemId); } final WzData strings = this.getStringData(itemId); if (strings == null) { return null; } final String ret = WzDataTool.getString("msg", strings, null); this.msgCache.put(itemId, ret); return ret; } public final short getItemMakeLevel(final int itemId) { if (this.itemMakeLevel.containsKey(itemId)) { return this.itemMakeLevel.get(itemId); } if (itemId / 10000 != 400) { return 0; } final short lvl = (short) WzDataTool.getIntConvert("info/lv", this.getItemData(itemId), 0); this.itemMakeLevel.put(itemId, lvl); return lvl; } public final ItemConsumeType isConsumeOnPickup(final int itemId) { // 0 = not, 1 = consume on pickup, 2 = consume + party if (this.consumeOnPickupCache.containsKey(itemId)) { return this.consumeOnPickupCache.get(itemId); } final WzData data = this.getItemData(itemId); byte consume = (byte) WzDataTool.getIntConvert("spec/consumeOnPickup", data, 0); if (consume == 0) { consume = (byte) WzDataTool.getIntConvert("specEx/consumeOnPickup", data, 0); } if (consume == 1) { if (WzDataTool.getIntConvert("spec/party", this.getItemData(itemId), 0) > 0) { consume = 2; } } final ItemConsumeType type = ItemConsumeType.fromNumber(consume); this.consumeOnPickupCache.put(itemId, type); return type; } public final boolean isDropRestricted(final int itemId) { if (this.dropRestrictionCache.containsKey(itemId)) { return this.dropRestrictionCache.get(itemId); } final WzData data = this.getItemData(itemId); boolean trade = false; if (WzDataTool.getIntConvert("info/tradeBlock", data, 0) == 1 || WzDataTool.getIntConvert("info/quest", data, 0) == 1) { trade = true; } this.dropRestrictionCache.put(itemId, trade); return trade; } public final boolean isPickupRestricted(final int itemId) { if (this.pickupRestrictionCache.containsKey(itemId)) { return this.pickupRestrictionCache.get(itemId); } final boolean isRestricted = WzDataTool.getIntConvert("info/only", this.getItemData(itemId), 0) == 1; this.pickupRestrictionCache.put(itemId, isRestricted); return isRestricted; } public final int getStateChangeItem(final int itemId) { if (this.stateChangeCache.containsKey(itemId)) { return this.stateChangeCache.get(itemId); } final int triggerItem = WzDataTool.getIntConvert("info/stateChangeItem", this.getItemData(itemId), 0); this.stateChangeCache.put(itemId, triggerItem); return triggerItem; } public final boolean isKarmaEnabled(final int itemId, final int karmaID) { if (this.karmaEnabledCache.containsKey(itemId)) { return this.karmaEnabledCache.get(itemId) == karmaID % 10 + 1; } final int bRestricted = WzDataTool.getIntConvert("info/tradeAvailable", this.getItemData(itemId), 0); this.karmaEnabledCache.put(itemId, bRestricted); return bRestricted == karmaID % 10 + 1; } public final RewardSetInfo getRewardSet(final int itemId) { if (this.RewardItem.containsKey(itemId)) { return this.RewardItem.get(itemId); } final WzData data = this.getItemData(itemId); if (data == null) { return null; } final WzData rewards = data.getChildByPath("reward"); if (rewards == null) { return null; } final List<RewardItemInfo> all = new ArrayList<RewardItemInfo>(); for (final WzData reward : rewards) { final RewardItemInfo info = new RewardItemInfo(reward); all.add(info); } final RewardSetInfo set = new RewardSetInfo(all); this.RewardItem.put(itemId, set); return set; } public final Map<String, Integer> getSkillStats(final int itemId) { if (this.SkillStatsCache.containsKey(itemId)) { return this.SkillStatsCache.get(itemId); } if (!(itemId / 10000 == 228 || itemId / 10000 == 229)) { // Skillbook and mastery book return null; } final WzData item = this.getItemData(itemId); if (item == null) { return null; } final WzData info = item.getChildByPath("info"); if (info == null) { return null; } final Map<String, Integer> ret = Maps.newLinkedHashMap(); for (final WzData data : info.getChildren()) { if (data.getName().startsWith("inc")) { ret.put(data.getName().substring(3), WzDataTool.getIntConvert(data)); } } ret.put("masterLevel", WzDataTool.getInt("masterLevel", info, 0)); ret.put("reqSkillLevel", WzDataTool.getInt("reqSkillLevel", info, 0)); ret.put("success", WzDataTool.getInt("success", info, 0)); final WzData skill = info.getChildByPath("skill"); for (int i = 0; i < skill.getChildren().size(); i++) { // List of allowed skillIds ret.put("skillid" + i, WzDataTool.getInt(Integer.toString(i), skill, 0)); } this.SkillStatsCache.put(itemId, ret); return ret; } public final List<Integer> petsCanConsume(final int itemId) { final List<Integer> ret = Lists.newArrayList(); final WzData data = this.getItemData(itemId); int curPetId = 0; final int size = data.getChildren().size(); for (int i = 0; i < size; i++) { curPetId = WzDataTool.getInt("spec/" + Integer.toString(i), data, 0); if (curPetId == 0) { break; } ret.add(Integer.valueOf(curPetId)); } return ret; } public final boolean isQuestItem(final int itemId) { if (this.isQuestItemCache.containsKey(itemId)) { return this.isQuestItemCache.get(itemId); } final boolean questItem = WzDataTool.getIntConvert("info/quest", this.getItemData(itemId), 0) == 1; this.isQuestItemCache.put(itemId, questItem); return questItem; } public final boolean isCash(final int itemid) { if (this.getEquipStats(itemid) == null) { return GameConstants.getInventoryType(itemid) == InventoryType.CASH; } return GameConstants.getInventoryType(itemid) == InventoryType.CASH || this.getEquipStats(itemid).get("cash") > 0; } public Equip hardcoreItem(final Equip equip, final short stat) { equip.setStr(stat); equip.setDex(stat); equip.setInt(stat); equip.setLuk(stat); equip.setMatk(stat); equip.setWatk(stat); equip.setAcc(stat); equip.setAvoid(stat); equip.setJump(stat); equip.setSpeed(stat); equip.setWdef(stat); equip.setMdef(stat); equip.setHp(stat); equip.setMp(stat); return equip; } }