MapleItemInformationProvider.java
上传用户:gwt600
上传日期:2021-06-03
资源大小:704k
文件大小:41k
源码类别:

游戏

开发平台:

Java

  1. /*
  2. This file is part of the OdinMS Maple Story Server
  3. Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc> 
  4. Matthias Butz <matze@odinms.de>
  5. Jan Christian Meyer <vimes@odinms.de>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Affero General Public License version 3
  8. as published by the Free Software Foundation. You may not use, modify
  9. or distribute this program under any other version of the
  10. GNU Affero General Public License.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU Affero General Public License for more details.
  15. You should have received a copy of the GNU Affero General Public License
  16. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18. /*
  19.  * MapleItemInformationProvider.java
  20.  * 
  21.  * Created on 26. November 2007, 21:58
  22.  */
  23. package net.sf.odinms.server;
  24. import java.io.File;
  25. import java.util.ArrayList;
  26. import java.util.HashMap;
  27. import java.util.LinkedHashMap;
  28. import java.util.List;
  29. import java.util.Map;
  30. import java.util.Random;
  31. import java.util.Map.Entry;
  32. import net.sf.odinms.client.Equip;
  33. import net.sf.odinms.client.IItem;
  34. import net.sf.odinms.client.MapleClient;
  35. import net.sf.odinms.client.MapleInventoryType;
  36. import net.sf.odinms.client.MapleWeaponType;
  37. import net.sf.odinms.client.SkillFactory;
  38. import net.sf.odinms.net.channel.ChannelServer;
  39. import net.sf.odinms.provider.MapleData;
  40. import net.sf.odinms.provider.MapleDataDirectoryEntry;
  41. import net.sf.odinms.provider.MapleDataFileEntry;
  42. import net.sf.odinms.provider.MapleDataProvider;
  43. import net.sf.odinms.provider.MapleDataProviderFactory;
  44. import net.sf.odinms.provider.MapleDataTool;
  45. import net.sf.odinms.tools.Pair;
  46. /**
  47.  * 
  48.  * @author Matze
  49.  * 
  50.  * TODO: make faster
  51.  * 
  52.  */
  53. public class MapleItemInformationProvider {
  54.     private static MapleItemInformationProvider instance = null;
  55.     protected MapleDataProvider itemData;
  56.     protected MapleDataProvider equipData;
  57.     protected MapleDataProvider stringData;
  58.     protected MapleData cashStringData;
  59.     protected MapleData consumeStringData;
  60.     protected MapleData eqpStringData;
  61.     protected MapleData etcStringData;
  62.     protected MapleData insStringData;
  63.     protected MapleData petStringData;
  64.     protected Map<Integer, MapleInventoryType> inventoryTypeCache = new HashMap<Integer, MapleInventoryType>();
  65.     protected Map<Integer, Short> slotMaxCache = new HashMap<Integer, Short>();
  66.     protected Map<Integer, MapleStatEffect> itemEffects = new HashMap<Integer, MapleStatEffect>();
  67.     protected Map<Integer, Map<String, Integer>> equipStatsCache = new HashMap<Integer, Map<String, Integer>>();
  68.     protected Map<Integer, Equip> equipCache = new HashMap<Integer, Equip>();
  69.     protected Map<Integer, Double> priceCache = new HashMap<Integer, Double>();
  70.     protected Map<Integer, Integer> wholePriceCache = new HashMap<Integer, Integer>();
  71.     protected Map<Integer, Integer> projectileWatkCache = new HashMap<Integer, Integer>();
  72.     protected Map<Integer, String> nameCache = new HashMap<Integer, String>();
  73.     protected Map<Integer, String> descCache = new HashMap<Integer, String>();
  74.     protected Map<Integer, String> msgCache = new HashMap<Integer, String>();
  75.     protected Map<Integer, Boolean> dropRestrictionCache = new HashMap<Integer, Boolean>();
  76.     protected Map<Integer, Boolean> pickupRestrictionCache = new HashMap<Integer, Boolean>();
  77.     protected List<Pair<Integer, String>> itemNameCache = new ArrayList<Pair<Integer, String>>();
  78.     protected Map<Integer, Integer> getMesoCache = new HashMap<Integer, Integer>();
  79.     protected Map<Integer, Integer> getExpCache = new HashMap<Integer, Integer>();
  80.     private static Random rand = new Random();
  81.     /** Creates a new instance of MapleItemInformationProvider */
  82.     protected MapleItemInformationProvider() {
  83.         itemData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/Item.wz"));
  84.         equipData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/Character.wz"));
  85.         stringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz"));
  86.         cashStringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")).getData("Cash.img");
  87.         consumeStringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")).getData("Consume.img");
  88.         eqpStringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")).getData("Eqp.img");
  89.         etcStringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")).getData("Etc.img");
  90.         insStringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")).getData("Ins.img");
  91.         petStringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")).getData("Pet.img");
  92.     }
  93.     public static MapleItemInformationProvider getInstance() {
  94.         if (instance == null) {
  95.             instance = new MapleItemInformationProvider();
  96.         }
  97.         return instance;
  98.     }
  99.     /* returns the inventory type for the specified item id */
  100.     public MapleInventoryType getInventoryType(int itemId) {
  101.         if (inventoryTypeCache.containsKey(itemId)) {
  102.             return inventoryTypeCache.get(itemId);
  103.         }
  104.         MapleInventoryType ret;
  105.         String idStr = "0" + String.valueOf(itemId);
  106.         // first look in items...
  107.         MapleDataDirectoryEntry root = itemData.getRoot();
  108.         for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
  109.             // we should have .img files here beginning with the first 4 IID
  110.             for (MapleDataFileEntry iFile : topDir.getFiles()) {
  111.                 if (iFile.getName().equals(idStr.substring(0, 4) + ".img")) {
  112.                     ret = MapleInventoryType.getByWZName(topDir.getName());
  113.                     inventoryTypeCache.put(itemId, ret);
  114.                     return ret;
  115.                 } else if (iFile.getName().equals(idStr.substring(1) + ".img")) {
  116.                     ret = MapleInventoryType.getByWZName(topDir.getName());
  117.                     inventoryTypeCache.put(itemId, ret);
  118.                     return ret;
  119.                 }
  120.             }
  121.         }
  122.         // not found? maybe its equip...
  123.         root = equipData.getRoot();
  124.         for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
  125.             for (MapleDataFileEntry iFile : topDir.getFiles()) {
  126.                 if (iFile.getName().equals(idStr + ".img")) {
  127.                     ret = MapleInventoryType.EQUIP;
  128.                     inventoryTypeCache.put(itemId, ret);
  129.                     return ret;
  130.                 }
  131.             }
  132.         }
  133.         ret = MapleInventoryType.UNDEFINED;
  134.         inventoryTypeCache.put(itemId, ret);
  135.         return ret;
  136.     }
  137.     public List<Pair<Integer, String>> getAllItems() {
  138.         if (itemNameCache.size() != 0) {
  139.             return itemNameCache;
  140.         }
  141.         List<Pair<Integer, String>> itemPairs = new ArrayList<Pair<Integer, String>>();
  142.         MapleData itemsData;
  143.         itemsData = stringData.getData("Cash.img");
  144.         for (MapleData itemFolder : itemsData.getChildren()) {
  145.             int itemId = Integer.parseInt(itemFolder.getName());
  146.             String itemName = MapleDataTool.getString("name", itemFolder, "NO-NAME");
  147.             itemPairs.add(new Pair<Integer, String>(itemId, itemName));
  148.         }
  149.         itemsData = stringData.getData("Consume.img");
  150.         for (MapleData itemFolder : itemsData.getChildren()) {
  151.             int itemId = Integer.parseInt(itemFolder.getName());
  152.             String itemName = MapleDataTool.getString("name", itemFolder, "NO-NAME");
  153.             itemPairs.add(new Pair<Integer, String>(itemId, itemName));
  154.         }
  155.         itemsData = stringData.getData("Eqp.img").getChildByPath("Eqp");
  156.         for (MapleData eqpType : itemsData.getChildren()) {
  157.             for (MapleData itemFolder : eqpType.getChildren()) {
  158.                 int itemId = Integer.parseInt(itemFolder.getName());
  159.                 String itemName = MapleDataTool.getString("name", itemFolder, "NO-NAME");
  160.                 itemPairs.add(new Pair<Integer, String>(itemId, itemName));
  161.             }
  162.         }
  163.         itemsData = stringData.getData("Etc.img").getChildByPath("Etc");
  164.         for (MapleData itemFolder : itemsData.getChildren()) {
  165.             int itemId = Integer.parseInt(itemFolder.getName());
  166.             String itemName = MapleDataTool.getString("name", itemFolder, "NO-NAME");
  167.             itemPairs.add(new Pair<Integer, String>(itemId, itemName));
  168.         }
  169.         itemsData = stringData.getData("Ins.img");
  170.         for (MapleData itemFolder : itemsData.getChildren()) {
  171.             int itemId = Integer.parseInt(itemFolder.getName());
  172.             String itemName = MapleDataTool.getString("name", itemFolder, "NO-NAME");
  173.             itemPairs.add(new Pair<Integer, String>(itemId, itemName));
  174.         }
  175.         itemsData = stringData.getData("Pet.img");
  176.         for (MapleData itemFolder : itemsData.getChildren()) {
  177.             int itemId = Integer.parseInt(itemFolder.getName());
  178.             String itemName = MapleDataTool.getString("name", itemFolder, "NO-NAME");
  179.             itemPairs.add(new Pair<Integer, String>(itemId, itemName));
  180.         }
  181.         return itemPairs;
  182.     }
  183.     protected MapleData getStringData(int itemId) {
  184.         String cat = "null";
  185.         MapleData theData;
  186.         if (itemId >= 5010000) {
  187.             theData = cashStringData;
  188.         } else if (itemId >= 2000000 && itemId < 3000000) {
  189.             theData = consumeStringData;
  190.         } else if (itemId >= 1010000 && itemId < 1040000 || itemId >= 1122000 && itemId < 1123000) {
  191.             theData = eqpStringData;
  192.             cat = "Accessory";
  193.         } else if (itemId >= 1000000 && itemId < 1010000) {
  194.             theData = eqpStringData;
  195.             cat = "Cap";
  196.         } else if (itemId >= 1102000 && itemId < 1103000) {
  197.             theData = eqpStringData;
  198.             cat = "Cape";
  199.         } else if (itemId >= 1040000 && itemId < 1050000) {
  200.             theData = eqpStringData;
  201.             cat = "Coat";
  202.         } else if (itemId >= 20000 && itemId < 22000) {
  203.             theData = eqpStringData;
  204.             cat = "Face";
  205.         } else if (itemId >= 1080000 && itemId < 1090000) {
  206.             theData = eqpStringData;
  207.             cat = "Glove";
  208.         } else if (itemId >= 30000 && itemId < 32000) {
  209.             theData = eqpStringData;
  210.             cat = "Hair";
  211.         } else if (itemId >= 1050000 && itemId < 1060000) {
  212.             theData = eqpStringData;
  213.             cat = "Longcoat";
  214.         } else if (itemId >= 1060000 && itemId < 1070000) {
  215.             theData = eqpStringData;
  216.             cat = "Pants";
  217.         } else if (itemId >= 1802000 && itemId < 1810000) {
  218.             theData = eqpStringData;
  219.             cat = "PetEquip";
  220.         } else if (itemId >= 1112000 && itemId < 1120000) {
  221.             theData = eqpStringData;
  222.             cat = "Ring";
  223.         } else if (itemId >= 1092000 && itemId < 1100000) {
  224.             theData = eqpStringData;
  225.             cat = "Shield";
  226.         } else if (itemId >= 1070000 && itemId < 1080000) {
  227.             theData = eqpStringData;
  228.             cat = "Shoes";
  229.         } else if (itemId >= 1900000 && itemId < 2000000) {
  230.             theData = eqpStringData;
  231.             cat = "Taming";
  232.         } else if (itemId >= 1300000 && itemId < 1800000) {
  233.             theData = eqpStringData;
  234.             cat = "Weapon";
  235.         } else if (itemId >= 4000000 && itemId < 5000000) {
  236.             theData = etcStringData;
  237.         } else if (itemId >= 3000000 && itemId < 4000000) {
  238.             theData = insStringData;
  239.         } else if (itemId >= 5000000 && itemId < 5010000) {
  240.             theData = petStringData;
  241.         } else {
  242.             return null;
  243.         }
  244.         if (cat.equalsIgnoreCase("null")) {
  245.             return theData.getChildByPath(String.valueOf(itemId));
  246.         } else {
  247.             return theData.getChildByPath(cat + "/" + itemId);
  248.         }
  249.     }
  250.     protected MapleData getItemData(int itemId) {
  251.         MapleData ret = null;
  252.         String idStr = "0" + String.valueOf(itemId);
  253.         MapleDataDirectoryEntry root = itemData.getRoot();
  254.         for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
  255.             // we should have .img files here beginning with the first 4 IID
  256.             for (MapleDataFileEntry iFile : topDir.getFiles()) {
  257.                 if (iFile.getName().equals(idStr.substring(0, 4) + ".img")) {
  258.                     ret = itemData.getData(topDir.getName() + "/" + iFile.getName());
  259.                     if (ret == null) {
  260.                         return null;
  261.                     }
  262.                     ret = ret.getChildByPath(idStr);
  263.                     return ret;
  264.                 } else if (iFile.getName().equals(idStr.substring(1) + ".img")) {
  265.                     return itemData.getData(topDir.getName() + "/" + iFile.getName());
  266.                 }
  267.             }
  268.         }
  269.         root = equipData.getRoot();
  270.         for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
  271.             for (MapleDataFileEntry iFile : topDir.getFiles()) {
  272.                 if (iFile.getName().equals(idStr + ".img")) {
  273.                     return equipData.getData(topDir.getName() + "/" + iFile.getName());
  274.                 }
  275.             }
  276.         }
  277.         return ret;
  278.     }
  279.     /** returns the maximum of items in one slot */
  280.     public short getSlotMax(MapleClient c, int itemId) {
  281.         if (slotMaxCache.containsKey(itemId)) {
  282.             return slotMaxCache.get(itemId);
  283.         }
  284.         short ret = 0;
  285.         MapleData item = getItemData(itemId);
  286.         if (item != null) {
  287.             MapleData smEntry = item.getChildByPath("info/slotMax");
  288.             if (smEntry == null) {
  289.                 if (getInventoryType(itemId).getType() == MapleInventoryType.EQUIP.getType()) {
  290.                     ret = 1;
  291.                 } else {
  292.                     ret = 100;
  293.                 }
  294.             } else {
  295.                 if (isThrowingStar(itemId) || isBullet(itemId) || (MapleDataTool.getInt(smEntry) == 0)) {
  296.                     ret = 1;
  297.                 }
  298.                 ret = (short) MapleDataTool.getInt(smEntry);
  299.                 if (isThrowingStar(itemId)) {
  300.                     ret += c.getPlayer().getSkillLevel(SkillFactory.getSkill(4100000)) * 10;
  301.                 } else {
  302.                     ret += c.getPlayer().getSkillLevel(SkillFactory.getSkill(5200000)) * 10;
  303.                 }
  304.             }
  305.         }
  306.         if (!isThrowingStar(itemId) && !isBullet(itemId)) {
  307.             slotMaxCache.put(itemId, ret);
  308.         }
  309.         return ret;
  310.     }
  311.     public int getMeso(int itemId) {
  312.         if (getMesoCache.containsKey(itemId)) {
  313.             return getMesoCache.get(itemId);
  314.         }
  315.         MapleData item = getItemData(itemId);
  316.         if (item == null) {
  317.             return -1;
  318.         }
  319.         int pEntry = 0;
  320.         MapleData pData = item.getChildByPath("info/meso");
  321.         if (pData == null) {
  322.             return -1;
  323.         }
  324.         pEntry = MapleDataTool.getInt(pData);
  325.         getMesoCache.put(itemId, pEntry);
  326.         return pEntry;
  327.     }
  328.     public int getExpCache(int itemId) {
  329.         if (this.getExpCache.containsKey(itemId)) {
  330.             return getExpCache.get(itemId);
  331.         }
  332.         MapleData item = getItemData(itemId);
  333.         if (item == null) {
  334.             return 0;
  335.         }
  336.         int pEntry = 0;
  337.         MapleData pData = item.getChildByPath("spec/exp");
  338.         if (pData == null) {
  339.             return 0;
  340.         }
  341.         pEntry = MapleDataTool.getInt(pData);
  342.         getExpCache.put(itemId, pEntry);
  343.         return pEntry;
  344.     }
  345.     public int getWholePrice(int itemId) {
  346.         if (wholePriceCache.containsKey(itemId)) {
  347.             return wholePriceCache.get(itemId);
  348.         }
  349.         MapleData item = getItemData(itemId);
  350.         if (item == null) {
  351.             return -1;
  352.         }
  353.         int pEntry = 0;
  354.         MapleData pData = item.getChildByPath("info/price");
  355.         if (pData == null) {
  356.             return -1;
  357.         }
  358.         pEntry = MapleDataTool.getInt(pData);
  359.         wholePriceCache.put(itemId, pEntry);
  360.         return pEntry;
  361.     }
  362.     public double getPrice(int itemId) {
  363.         if (priceCache.containsKey(itemId)) {
  364.             return priceCache.get(itemId);
  365.         }
  366.         MapleData item = getItemData(itemId);
  367.         if (item == null) {
  368.             return -1;
  369.         }
  370.         double pEntry = 0.0;
  371.         MapleData pData = item.getChildByPath("info/unitPrice");
  372.         if (pData != null) {
  373.             try {
  374.                 pEntry = MapleDataTool.getDouble(pData);
  375.             } catch (Exception e) {
  376.                 pEntry = (double) MapleDataTool.getInt(pData);
  377.             }
  378.         } else {
  379.             pData = item.getChildByPath("info/price");
  380.             if (pData == null) {
  381.                 return -1;
  382.             }
  383.             pEntry = (double) MapleDataTool.getInt(pData);
  384.         }
  385.         priceCache.put(itemId, pEntry);
  386.         return pEntry;
  387.     }
  388.     protected Map<String, Integer> getEquipStats(int itemId) {
  389.         if (equipStatsCache.containsKey(itemId)) {
  390.             return equipStatsCache.get(itemId);
  391.         }
  392.         Map<String, Integer> ret = new LinkedHashMap<String, Integer>();
  393.         MapleData item = getItemData(itemId);
  394.         if (item == null) {
  395.             return null;
  396.         }
  397.         MapleData info = item.getChildByPath("info");
  398.         if (info == null) {
  399.             return null;
  400.         }
  401.         for (MapleData data : info.getChildren()) {
  402.             if (data.getName().startsWith("inc")) {
  403.                 ret.put(data.getName().substring(3), MapleDataTool.getIntConvert(data));
  404.             }
  405.         }
  406.         ret.put("tuc", MapleDataTool.getInt("tuc", info, 0));
  407.         ret.put("reqLevel", MapleDataTool.getInt("reqLevel", info, 0));
  408.         ret.put("cursed", MapleDataTool.getInt("cursed", info, 0));
  409.         ret.put("success", MapleDataTool.getInt("success", info, 0));
  410.         equipStatsCache.put(itemId, ret);
  411.         return ret;
  412.     }
  413.     public int getReqLevel(int itemId) {
  414.         final Integer req = getEquipStats(itemId).get("reqLevel");
  415.         return req == null ? 0 : req.intValue();
  416.     }
  417.     public List<Integer> getScrollReqs(int itemId) {
  418.         List<Integer> ret = new ArrayList<Integer>();
  419.         MapleData data = getItemData(itemId);
  420.         data = data.getChildByPath("req");
  421.         if (data == null) {
  422.             return ret;
  423.         }
  424.         for (MapleData req : data.getChildren()) {
  425.             ret.add(MapleDataTool.getInt(req));
  426.         }
  427.         return ret;
  428.     }
  429.     public boolean isWeapon(int itemId) {
  430.         return itemId >= 1302000 && itemId < 1492024;
  431.     }
  432.     public MapleWeaponType getWeaponType(int itemId) {
  433.         int cat = itemId / 10000;
  434.         cat = cat % 100;
  435.         switch (cat) {
  436.             case 30:
  437.                 return MapleWeaponType.SWORD1H;
  438.             case 31:
  439.                 return MapleWeaponType.AXE1H;
  440.             case 32:
  441.                 return MapleWeaponType.BLUNT1H;
  442.             case 33:
  443.                 return MapleWeaponType.DAGGER;
  444.             case 37:
  445.                 return MapleWeaponType.WAND;
  446.             case 38:
  447.                 return MapleWeaponType.STAFF;
  448.             case 40:
  449.                 return MapleWeaponType.SWORD2H;
  450.             case 41:
  451.                 return MapleWeaponType.AXE2H;
  452.             case 42:
  453.                 return MapleWeaponType.BLUNT2H;
  454.             case 43:
  455.                 return MapleWeaponType.SPEAR;
  456.             case 44:
  457.                 return MapleWeaponType.POLE_ARM;
  458.             case 45:
  459.                 return MapleWeaponType.BOW;
  460.             case 46:
  461.                 return MapleWeaponType.CROSSBOW;
  462.             case 47:
  463.                 return MapleWeaponType.CLAW;
  464.             case 48:
  465.                 return MapleWeaponType.KNUCKLE;
  466.             case 49:
  467.                 return MapleWeaponType.GUN;
  468.         }
  469.         return MapleWeaponType.NOT_A_WEAPON;
  470.     }
  471.     public boolean isShield(int itemId) {
  472.         int cat = itemId / 10000;
  473.         cat = cat % 100;
  474.         return cat == 9;
  475.     }
  476.     public boolean isEquip(int itemId) {
  477.         return itemId / 1000000 == 1;
  478.     }
  479.     public boolean isCleanSlate(int scrollId) {
  480.         switch (scrollId) {
  481.             case 2049000:
  482.             case 2049001:
  483.             case 2049002:
  484.             case 2049003:
  485.                 return true;
  486.         }
  487.         return false;
  488.     }
  489.     public IItem scrollEquipWithId(MapleClient c, IItem equip, int scrollId, boolean usingWhiteScroll) {
  490.         boolean noFail = false;
  491.         if (c.getPlayer().haveItem(2022118, 1, false, true)) {
  492.             noFail = true;
  493.         }
  494.         boolean isGM = false;
  495.         if (c.getPlayer().isGM()) {
  496.             isGM = true;
  497.         }
  498.         if (equip instanceof Equip) {
  499.             Equip nEquip = (Equip) equip;
  500.             Map<String, Integer> stats = this.getEquipStats(scrollId);
  501.             Map<String, Integer> eqstats = this.getEquipStats(equip.getItemId());
  502.             if ((nEquip.getUpgradeSlots() > 0 || isCleanSlate(scrollId)) && Math.ceil(Math.random() * 100.0) <= stats.get("success") || isGM || noFail) {
  503.                 switch (scrollId) {
  504.                     case 2049000:
  505.                     case 2049001:
  506.                     case 2049002:
  507.                     case 2049003:
  508.                         if (nEquip.getLevel() + nEquip.getUpgradeSlots() < eqstats.get("tuc")) {
  509.                             byte newSlots = (byte) (nEquip.getUpgradeSlots() + 1);
  510.                             nEquip.setUpgradeSlots(newSlots);
  511.                         }
  512.                         break;
  513.                     case 2049100:
  514.                     case 2049101:
  515.                     case 2049102:
  516.                         int increase = 1;
  517.                         if (Math.ceil(Math.random() * 100.0) <= 50) {
  518.                             increase = increase * -1;
  519.                         }
  520.                         if (nEquip.getStr() > 0) {
  521.                             short newStat = (short) (nEquip.getStr() + Math.ceil(Math.random() * 5.0) * increase);
  522.                             nEquip.setStr(newStat);
  523.                         }
  524.                         if (nEquip.getDex() > 0) {
  525.                             short newStat = (short) (nEquip.getDex() + Math.ceil(Math.random() * 5.0) * increase);
  526.                             nEquip.setDex(newStat);
  527.                         }
  528.                         if (nEquip.getInt() > 0) {
  529.                             short newStat = (short) (nEquip.getInt() + Math.ceil(Math.random() * 5.0) * increase);
  530.                             nEquip.setInt(newStat);
  531.                         }
  532.                         if (nEquip.getLuk() > 0) {
  533.                             short newStat = (short) (nEquip.getLuk() + Math.ceil(Math.random() * 5.0) * increase);
  534.                             nEquip.setLuk(newStat);
  535.                         }
  536.                         if (nEquip.getWatk() > 0) {
  537.                             short newStat = (short) (nEquip.getWatk() + Math.ceil(Math.random() * 5.0) * increase);
  538.                             nEquip.setWatk(newStat);
  539.                         }
  540.                         if (nEquip.getWdef() > 0) {
  541.                             short newStat = (short) (nEquip.getWdef() + Math.ceil(Math.random() * 5.0) * increase);
  542.                             nEquip.setWdef(newStat);
  543.                         }
  544.                         if (nEquip.getMatk() > 0) {
  545.                             short newStat = (short) (nEquip.getMatk() + Math.ceil(Math.random() * 5.0) * increase);
  546.                             nEquip.setMatk(newStat);
  547.                         }
  548.                         if (nEquip.getMdef() > 0) {
  549.                             short newStat = (short) (nEquip.getMdef() + Math.ceil(Math.random() * 5.0) * increase);
  550.                             nEquip.setMdef(newStat);
  551.                         }
  552.                         if (nEquip.getAcc() > 0) {
  553.                             short newStat = (short) (nEquip.getAcc() + Math.ceil(Math.random() * 5.0) * increase);
  554.                             nEquip.setAcc(newStat);
  555.                         }
  556.                         if (nEquip.getAvoid() > 0) {
  557.                             short newStat = (short) (nEquip.getAvoid() + Math.ceil(Math.random() * 5.0) * increase);
  558.                             nEquip.setAvoid(newStat);
  559.                         }
  560.                         if (nEquip.getSpeed() > 0) {
  561.                             short newStat = (short) (nEquip.getSpeed() + Math.ceil(Math.random() * 5.0) * increase);
  562.                             nEquip.setSpeed(newStat);
  563.                         }
  564.                         if (nEquip.getJump() > 0) {
  565.                             short newStat = (short) (nEquip.getJump() + Math.ceil(Math.random() * 5.0) * increase);
  566.                             nEquip.setJump(newStat);
  567.                         }
  568.                         if (nEquip.getHp() > 0) {
  569.                             short newStat = (short) (nEquip.getHp() + Math.ceil(Math.random() * 5.0) * increase);
  570.                             nEquip.setHp(newStat);
  571.                         }
  572.                         if (nEquip.getMp() > 0) {
  573.                             short newStat = (short) (nEquip.getMp() + Math.ceil(Math.random() * 5.0) * increase);
  574.                             nEquip.setMp(newStat);
  575.                         }
  576.                         break;
  577.                     default:
  578.                         for (Entry<String, Integer> stat : stats.entrySet()) {
  579.                             if (stat.getKey().equals("STR")) {
  580.                                 nEquip.setStr((short) (nEquip.getStr() + stat.getValue().intValue()));
  581.                             } else if (stat.getKey().equals("DEX")) {
  582.                                 nEquip.setDex((short) (nEquip.getDex() + stat.getValue().intValue()));
  583.                             } else if (stat.getKey().equals("INT")) {
  584.                                 nEquip.setInt((short) (nEquip.getInt() + stat.getValue().intValue()));
  585.                             } else if (stat.getKey().equals("LUK")) {
  586.                                 nEquip.setLuk((short) (nEquip.getLuk() + stat.getValue().intValue()));
  587.                             } else if (stat.getKey().equals("PAD")) {
  588.                                 nEquip.setWatk((short) (nEquip.getWatk() + stat.getValue().intValue()));
  589.                             } else if (stat.getKey().equals("PDD")) {
  590.                                 nEquip.setWdef((short) (nEquip.getWdef() + stat.getValue().intValue()));
  591.                             } else if (stat.getKey().equals("MAD")) {
  592.                                 nEquip.setMatk((short) (nEquip.getMatk() + stat.getValue().intValue()));
  593.                             } else if (stat.getKey().equals("MDD")) {
  594.                                 nEquip.setMdef((short) (nEquip.getMdef() + stat.getValue().intValue()));
  595.                             } else if (stat.getKey().equals("ACC")) {
  596.                                 nEquip.setAcc((short) (nEquip.getAcc() + stat.getValue().intValue()));
  597.                             } else if (stat.getKey().equals("EVA")) {
  598.                                 nEquip.setAvoid((short) (nEquip.getAvoid() + stat.getValue().intValue()));
  599.                             } else if (stat.getKey().equals("Speed")) {
  600.                                 nEquip.setSpeed((short) (nEquip.getSpeed() + stat.getValue().intValue()));
  601.                             } else if (stat.getKey().equals("Jump")) {
  602.                                 nEquip.setJump((short) (nEquip.getJump() + stat.getValue().intValue()));
  603.                             } else if (stat.getKey().equals("MHP")) {
  604.                                 nEquip.setHp((short) (nEquip.getHp() + stat.getValue().intValue()));
  605.                             } else if (stat.getKey().equals("MMP")) {
  606.                                 nEquip.setMp((short) (nEquip.getMp() + stat.getValue().intValue()));
  607.                             } else if (stat.getKey().equals("afterImage")) {
  608.                             }
  609.                         }
  610.                         break;
  611.                 }
  612.                 if (noFail && !isGM) {
  613.                     MapleInventoryManipulator.removeById(c, MapleInventoryType.USE, 2022118, 1, true, false);
  614.                 }
  615.                 if (!isCleanSlate(scrollId)) {
  616.                     if (!isGM) {
  617.                         nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
  618.                     }
  619.                     nEquip.setLevel((byte) (nEquip.getLevel() + 1));
  620.                 }
  621.             } else {
  622.                 if (!usingWhiteScroll && !isCleanSlate(scrollId)) {
  623.                     nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
  624.                 }
  625.                 if (Math.ceil(1.0 + Math.random() * 100.0) < stats.get("cursed")) {
  626.                     // DESTROY :) (O.O!)
  627.                     return null;
  628.                 }
  629.             }
  630.         }
  631.         return equip;
  632.     }
  633.     public IItem getEquipById(int equipId) {
  634.         return getEquipById(equipId, -1);
  635.     }
  636.     public IItem getEquipById(int equipId, int ringId) {
  637.         Equip nEquip;
  638.         nEquip = new Equip(equipId, (byte) 0, ringId);
  639.         nEquip.setQuantity((short) 1);
  640.         Map<String, Integer> stats = this.getEquipStats(equipId);
  641.         if (stats != null) {
  642.             for (Entry<String, Integer> stat : stats.entrySet()) {
  643.                 if (stat.getKey().equals("STR")) {
  644.                     nEquip.setStr((short) stat.getValue().intValue());
  645.                 } else if (stat.getKey().equals("DEX")) {
  646.                     nEquip.setDex((short) stat.getValue().intValue());
  647.                 } else if (stat.getKey().equals("INT")) {
  648.                     nEquip.setInt((short) stat.getValue().intValue());
  649.                 } else if (stat.getKey().equals("LUK")) {
  650.                     nEquip.setLuk((short) stat.getValue().intValue());
  651.                 } else if (stat.getKey().equals("PAD")) {
  652.                     nEquip.setWatk((short) stat.getValue().intValue());
  653.                 } else if (stat.getKey().equals("PDD")) {
  654.                     nEquip.setWdef((short) stat.getValue().intValue());
  655.                 } else if (stat.getKey().equals("MAD")) {
  656.                     nEquip.setMatk((short) stat.getValue().intValue());
  657.                 } else if (stat.getKey().equals("MDD")) {
  658.                     nEquip.setMdef((short) stat.getValue().intValue());
  659.                 } else if (stat.getKey().equals("ACC")) {
  660.                     nEquip.setAcc((short) stat.getValue().intValue());
  661.                 } else if (stat.getKey().equals("EVA")) {
  662.                     nEquip.setAvoid((short) stat.getValue().intValue());
  663.                 } else if (stat.getKey().equals("Speed")) {
  664.                     nEquip.setSpeed((short) stat.getValue().intValue());
  665.                 } else if (stat.getKey().equals("Jump")) {
  666.                     nEquip.setJump((short) stat.getValue().intValue());
  667.                 } else if (stat.getKey().equals("MHP")) {
  668.                     nEquip.setHp((short) stat.getValue().intValue());
  669.                 } else if (stat.getKey().equals("MMP")) {
  670.                     nEquip.setMp((short) stat.getValue().intValue());
  671.                 } else if (stat.getKey().equals("tuc")) {
  672.                     nEquip.setUpgradeSlots((byte) stat.getValue().intValue());
  673.                 } else if (stat.getKey().equals("afterImage")) {
  674.                 }
  675.             }
  676.         }
  677.         equipCache.put(equipId, nEquip);
  678.         return nEquip.copy();
  679.     }
  680.     private short getRandStat(short defaultValue, int maxRange, short additionalStats) {
  681.         if (defaultValue == 0) {
  682.             return 0;
  683.         }
  684.         // vary no more than ceil of 10% of stat
  685.         int lMaxRange = (int) Math.min(Math.ceil(defaultValue * 0.1), maxRange);
  686.         return (short) ((defaultValue - lMaxRange) + Math.floor(rand.nextDouble() * (lMaxRange * 2 + 1 * additionalStats)));
  687.     }
  688.     public Equip randomizeStats(MapleClient c, Equip equip) {
  689.         short x = 1;
  690.         ChannelServer cserv = c.getChannelServer();
  691.         if (cserv.isGodlyItems() && Math.ceil(Math.random() * 100.0) <= cserv.getGodlyItemRate()) {
  692.             x = cserv.getItemMultiplier();
  693.         }
  694.         equip.setStr(getRandStat(equip.getStr(), 5, x)); // LMAOO Horrible way. But works :D
  695.         equip.setDex(getRandStat(equip.getDex(), 5, x));
  696.         equip.setInt(getRandStat(equip.getInt(), 5, x));
  697.         equip.setLuk(getRandStat(equip.getLuk(), 5, x));
  698.         equip.setMatk(getRandStat(equip.getMatk(), 5, x));
  699.         equip.setWatk(getRandStat(equip.getWatk(), 5, x));
  700.         equip.setAcc(getRandStat(equip.getAcc(), 5, x));
  701.         equip.setAvoid(getRandStat(equip.getAvoid(), 5, x));
  702.         equip.setJump(getRandStat(equip.getJump(), 5, x));
  703.         equip.setSpeed(getRandStat(equip.getSpeed(), 5, x));
  704.         equip.setWdef(getRandStat(equip.getWdef(), 10, x));
  705.         equip.setMdef(getRandStat(equip.getMdef(), 10, x));
  706.         equip.setHp(getRandStat(equip.getHp(), 10, x));
  707.         equip.setMp(getRandStat(equip.getMp(), 10, x));
  708.         return equip;
  709.     }
  710.     public Equip hardcoreItem(Equip equip, short stat) {
  711.         equip.setStr(stat);
  712.         equip.setDex(stat);
  713.         equip.setInt(stat);
  714.         equip.setLuk(stat);
  715.         equip.setMatk(stat);
  716.         equip.setWatk(stat);
  717.         equip.setAcc(stat);
  718.         equip.setAvoid(stat);
  719.         equip.setJump(stat);
  720.         equip.setSpeed(stat);
  721.         equip.setWdef(stat);
  722.         equip.setMdef(stat);
  723.         equip.setHp(stat);
  724.         equip.setMp(stat);
  725.         return equip;
  726.     }
  727.     public MapleStatEffect getItemEffect(int itemId) {
  728.         MapleStatEffect ret = itemEffects.get(Integer.valueOf(itemId));
  729.         if (ret == null) {
  730.             MapleData item = getItemData(itemId);
  731.             if (item == null) {
  732.                 return null;
  733.             }
  734.             MapleData spec = item.getChildByPath("spec");
  735.             ret = MapleStatEffect.loadItemEffectFromData(spec, itemId);
  736.             itemEffects.put(Integer.valueOf(itemId), ret);
  737.         }
  738.         return ret;
  739.     }
  740.     public int[][] getSummonMobs(int itemId) {
  741.         MapleData data = getItemData(itemId);
  742.         int theInt = data.getChildByPath("mob").getChildren().size();
  743.         int[][] mobs2spawn = new int[theInt][2];
  744.         for (int x = 0; x < theInt; x++) {
  745.             mobs2spawn[x][0] = MapleDataTool.getIntConvert("mob/" + x + "/id", data);
  746.             mobs2spawn[x][1] = MapleDataTool.getIntConvert("mob/" + x + "/prob", data);
  747.         }
  748.         return mobs2spawn;
  749.     }
  750.     public boolean isThrowingStar(int itemId) {
  751.         return (itemId >= 2070000 && itemId < 2080000);
  752.     }
  753.     public boolean isBullet(int itemId) {
  754.         int id = itemId / 10000;
  755.         if (id == 233) {
  756.             return true;
  757.         } else {
  758.             return false;
  759.         }
  760.     }
  761.     public boolean isRechargable(int itemId) {
  762.         int id = itemId / 10000;
  763.         if (id == 233 || id == 207) {
  764.             return true;
  765.         } else {
  766.             return false;
  767.         }
  768.     }
  769.     public boolean isOverall(int itemId) {
  770.         return itemId >= 1050000 && itemId < 1060000;
  771.     }
  772.     public boolean isPet(int itemId) {
  773.         return itemId >= 5000000 && itemId <= 5000100;
  774.     }
  775.     public boolean isArrowForCrossBow(int itemId) {
  776.         return itemId >= 2061000 && itemId < 2062000;
  777.     }
  778.     public boolean isArrowForBow(int itemId) {
  779.         return itemId >= 2060000 && itemId < 2061000;
  780.     }
  781.     public boolean isTwoHanded(int itemId) {
  782.         switch (getWeaponType(itemId)) {
  783.             case AXE2H:
  784.             case BLUNT2H:
  785.             case BOW:
  786.             case CLAW:
  787.             case CROSSBOW:
  788.             case POLE_ARM:
  789.             case SPEAR:
  790.             case SWORD2H:
  791.             case GUN:
  792.             case KNUCKLE:
  793.                 return true;
  794.             default:
  795.                 return false;
  796.         }
  797.     }
  798.     public boolean isTownScroll(int itemId) {
  799.         return (itemId >= 2030000 && itemId < 2030020);
  800.     }
  801.     public boolean isGun(int itemId) {
  802.         return itemId >= 1492000 && itemId <= 1492024;
  803.     }
  804.     public int getWatkForProjectile(int itemId) {
  805.         Integer atk = projectileWatkCache.get(itemId);
  806.         if (atk != null) {
  807.             return atk.intValue();
  808.         }
  809.         MapleData data = getItemData(itemId);
  810.         atk = Integer.valueOf(MapleDataTool.getInt("info/incPAD", data, 0));
  811.         projectileWatkCache.put(itemId, atk);
  812.         return atk.intValue();
  813.     }
  814.     public boolean canScroll(int scrollid, int itemid) {
  815.         int scrollCategoryQualifier = (scrollid / 100) % 100;
  816.         int itemCategoryQualifier = (itemid / 10000) % 100;
  817.         return scrollCategoryQualifier == itemCategoryQualifier;
  818.     }
  819.     public String getName(int itemId) {
  820.         if (nameCache.containsKey(itemId)) {
  821.             return nameCache.get(itemId);
  822.         }
  823.         MapleData strings = getStringData(itemId);
  824.         if (strings == null) {
  825.             return null;
  826.         }
  827.         String ret = MapleDataTool.getString("name", strings, null);
  828.         nameCache.put(itemId, ret);
  829.         return ret;
  830.     }
  831.     public String getDesc(int itemId) {
  832.         if (descCache.containsKey(itemId)) {
  833.             return descCache.get(itemId);
  834.         }
  835.         MapleData strings = getStringData(itemId);
  836.         if (strings == null) {
  837.             return null;
  838.         }
  839.         String ret = MapleDataTool.getString("desc", strings, null);
  840.         descCache.put(itemId, ret);
  841.         return ret;
  842.     }
  843.     public String getMsg(int itemId) {
  844.         if (msgCache.containsKey(itemId)) {
  845.             return msgCache.get(itemId);
  846.         }
  847.         MapleData strings = getStringData(itemId);
  848.         if (strings == null) {
  849.             return null;
  850.         }
  851.         String ret = MapleDataTool.getString("msg", strings, null);
  852.         msgCache.put(itemId, ret);
  853.         return ret;
  854.     }
  855.     public boolean isDropRestricted(int itemId) {
  856.         if (dropRestrictionCache.containsKey(itemId)) {
  857.             return dropRestrictionCache.get(itemId);
  858.         }
  859.         MapleData data = getItemData(itemId);
  860.         boolean bRestricted = MapleDataTool.getIntConvert("info/tradeBlock", data, 0) == 1;
  861.         if (!bRestricted) {
  862.             bRestricted = MapleDataTool.getIntConvert("info/quest", data, 0) == 1;
  863.         }
  864.         dropRestrictionCache.put(itemId, bRestricted);
  865.         return bRestricted;
  866.     }
  867.     public boolean isPickupRestricted(int itemId) {
  868.         if (pickupRestrictionCache.containsKey(itemId)) {
  869.             return pickupRestrictionCache.get(itemId);
  870.         }
  871.         MapleData data = getItemData(itemId);
  872.         boolean bRestricted = MapleDataTool.getIntConvert("info/only", data, 0) == 1;
  873.         pickupRestrictionCache.put(itemId, bRestricted);
  874.         return bRestricted;
  875.     }
  876.     public Map<String, Integer> getSkillStats(int itemId, double playerJob) {
  877.         Map<String, Integer> ret = new LinkedHashMap<String, Integer>();
  878.         MapleData item = getItemData(itemId);
  879.         if (item == null) {
  880.             return null;
  881.         }
  882.         MapleData info = item.getChildByPath("info");
  883.         if (info == null) {
  884.             return null;
  885.         }
  886.         for (MapleData data : info.getChildren()) {
  887.             if (data.getName().startsWith("inc")) {
  888.                 ret.put(data.getName().substring(3), MapleDataTool.getIntConvert(data));
  889.             }
  890.         }
  891.         ret.put("masterLevel", MapleDataTool.getInt("masterLevel", info, 0));
  892.         ret.put("reqSkillLevel", MapleDataTool.getInt("reqSkillLevel", info, 0));
  893.         ret.put("success", MapleDataTool.getInt("success", info, 0));
  894.         MapleData skill = info.getChildByPath("skill");
  895.         int curskill = 1;
  896.         int size = skill.getChildren().size();
  897.         for (int i = 0; i < size; i++) {
  898.             curskill = MapleDataTool.getInt(Integer.toString(i), skill, 0);
  899.             if (curskill == 0) // end - no more;
  900.             {
  901.                 break;
  902.             }
  903.             double skillJob = Math.floor(curskill / 10000);
  904.             if (skillJob == playerJob) {
  905.                 ret.put("skillid", curskill);
  906.                 break;
  907.             }
  908.         }
  909.         if (ret.get("skillid") == null) {
  910.             ret.put("skillid", 0);
  911.         }
  912.         return ret;
  913.     }
  914.     public List<Integer> petsCanConsume(int itemId) {
  915.         List<Integer> ret = new ArrayList<Integer>();
  916.         MapleData data = getItemData(itemId);
  917.         int curPetId = 0;
  918.         int size = data.getChildren().size();
  919.         for (int i = 0; i < size; i++) {
  920.             curPetId = MapleDataTool.getInt("spec/" + Integer.toString(i), data, 0);
  921.             if (curPetId == 0) {
  922.                 break;
  923.             }
  924.             ret.add(Integer.valueOf(curPetId));
  925.         }
  926.         return ret;
  927.     }
  928.     protected Map<Integer, Boolean> isQuestItemCache = new HashMap<Integer, Boolean>();
  929.     public boolean isQuestItem(int itemId) {
  930.         if (isQuestItemCache.containsKey(itemId)) {
  931.             return isQuestItemCache.get(itemId);
  932.         }
  933.         MapleData data = getItemData(itemId);
  934.         boolean questItem = MapleDataTool.getIntConvert("info/quest", data, 0) == 1;
  935.         isQuestItemCache.put(itemId, questItem);
  936.         return questItem;
  937.     }
  938.     public boolean isMiniDungeonMap(int mapId) {
  939.         switch (mapId) {
  940.             case 100020000:
  941.             case 105040304:
  942.             case 105050100:
  943.             case 221023400:
  944.                 return true;
  945.             default:
  946.                 return false;
  947.         }
  948.     }
  949. }