diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/LimitShop.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/LimitShop.xml
new file mode 100644
index 0000000000..ebfdcd1b9a
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/LimitShop.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/LimitShopCraft.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/LimitShopCraft.xml
new file mode 100644
index 0000000000..6f74ef90ad
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/LimitShopCraft.xml
@@ -0,0 +1,867 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/4rthClass/TyrrMaestro.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/4rthClass/TyrrMaestro.xml
index 97d23b3ef3..c555d26c92 100644
--- a/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/4rthClass/TyrrMaestro.xml
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/4rthClass/TyrrMaestro.xml
@@ -10,7 +10,7 @@
-
+
@@ -225,7 +225,6 @@
-
@@ -283,7 +282,6 @@
-
@@ -337,7 +335,6 @@
-
@@ -393,7 +390,6 @@
-
@@ -471,7 +467,6 @@
-
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/Commons.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/Commons.xml
index 8dad56627e..9223a45aac 100644
--- a/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/Commons.xml
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/Commons.xml
@@ -2,17 +2,7 @@
-
-
-
-
-
-
-
-
-
-
-
+
@@ -21,21 +11,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/raceSkillTree.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/raceSkillTree.xml
index 8062e8b415..8290f78b47 100644
--- a/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/raceSkillTree.xml
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/skillTrees/raceSkillTree.xml
@@ -20,6 +20,7 @@
+
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/items/60000-60099.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/items/60000-60099.xml
index 24c933e5e6..59a63d43fd 100644
--- a/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/items/60000-60099.xml
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/items/60000-60099.xml
@@ -135,18 +135,32 @@
-
+
+
+
+
+
-
-
+
+
+
+
-
+
+
+
+
+
-
-
+
+
+
+
-
@@ -835,4 +849,50 @@
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/items/82100-82199.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/items/82100-82199.xml
new file mode 100644
index 0000000000..48f640d6f0
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/items/82100-82199.xml
@@ -0,0 +1,73 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/skills/30900-30999.xml b/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/skills/30900-30999.xml
index c8df627ccd..6034acf3da 100644
--- a/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/skills/30900-30999.xml
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/stats/skills/30900-30999.xml
@@ -686,14 +686,14 @@
- icon.skill30943
+ icon.skill30944
85
P
5
-
+
- icon.skill30943
+ icon.skill30945
85
P
5
diff --git a/L2J_Mobius_10.0_MasterClass/dist/game/data/xsd/LimitShop.xsd b/L2J_Mobius_10.0_MasterClass/dist/game/data/xsd/LimitShop.xsd
new file mode 100644
index 0000000000..c0e0fe5fc3
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/dist/game/data/xsd/LimitShop.xsd
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
index 667e400fc7..9b603faacc 100644
--- a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
@@ -84,6 +84,8 @@ import org.l2jmobius.gameserver.data.xml.InitialEquipmentData;
import org.l2jmobius.gameserver.data.xml.InitialShortcutData;
import org.l2jmobius.gameserver.data.xml.ItemCrystallizationData;
import org.l2jmobius.gameserver.data.xml.KarmaData;
+import org.l2jmobius.gameserver.data.xml.LimitShopCraftData;
+import org.l2jmobius.gameserver.data.xml.LimitShopData;
import org.l2jmobius.gameserver.data.xml.LuckyGameData;
import org.l2jmobius.gameserver.data.xml.MultisellData;
import org.l2jmobius.gameserver.data.xml.NpcData;
@@ -289,6 +291,8 @@ public class GameServer
FishingData.getInstance();
HennaData.getInstance();
PrimeShopData.getInstance();
+ LimitShopData.getInstance();
+ LimitShopCraftData.getInstance();
CollectionData.getInstance();
PcCafePointsManager.getInstance();
AppearanceItemData.getInstance();
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/data/xml/LimitShopCraftData.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/data/xml/LimitShopCraftData.java
new file mode 100644
index 0000000000..089c095926
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/data/xml/LimitShopCraftData.java
@@ -0,0 +1,269 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.data.ItemTable;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.holders.LimitShopProductHolder;
+import org.l2jmobius.gameserver.model.items.Item;
+
+/**
+ * @author Mobius, GustavoFonseca
+ */
+public class LimitShopCraftData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(LimitShopData.class.getName());
+
+ private final List _products = new ArrayList<>();
+
+ protected LimitShopCraftData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _products.clear();
+ parseDatapackFile("data/LimitShopCraft.xml");
+
+ if (!_products.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _products.size() + " items.");
+ }
+ else
+ {
+ LOGGER.info(getClass().getSimpleName() + ": System is disabled.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ final NamedNodeMap at = n.getAttributes();
+ final Node attribute = at.getNamedItem("enabled");
+ if ((attribute != null) && Boolean.parseBoolean(attribute.getNodeValue()))
+ {
+ for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("product".equalsIgnoreCase(d.getNodeName()))
+ {
+ NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ final StatSet set = new StatSet();
+ for (int i = 0; i < attrs.getLength(); i++)
+ {
+ att = attrs.item(i);
+ set.set(att.getNodeName(), att.getNodeValue());
+ }
+
+ final int id = parseInteger(attrs, "id");
+ final int category = parseInteger(attrs, "category");
+ final int minLevel = parseInteger(attrs, "minLevel", 1);
+ final int maxLevel = parseInteger(attrs, "maxLevel", 999);
+ final int[] ingredientIds = new int[5];
+ ingredientIds[0] = 0;
+ ingredientIds[1] = 0;
+ ingredientIds[2] = 0;
+ ingredientIds[3] = 0;
+ ingredientIds[4] = 0;
+ final long[] ingredientQuantities = new long[5];
+ ingredientQuantities[0] = 0;
+ ingredientQuantities[1] = 0;
+ ingredientQuantities[2] = 0;
+ ingredientQuantities[3] = 0;
+ ingredientQuantities[4] = 0;
+ final int[] ingredientEnchants = new int[5];
+ ingredientEnchants[0] = 0;
+ ingredientEnchants[1] = 0;
+ ingredientEnchants[2] = 0;
+ ingredientEnchants[3] = 0;
+ ingredientEnchants[4] = 0;
+ int productionId = 0;
+ int productionId2 = 0;
+ int productionId3 = 0;
+ int productionId4 = 0;
+ int productionId5 = 0;
+ long count = 1L;
+ long count2 = 1L;
+ long count3 = 1L;
+ long count4 = 1L;
+ long count5 = 1L;
+ float chance = 100f;
+ float chance2 = 100f;
+ float chance3 = 100f;
+ float chance4 = 100f;
+ int accountDailyLimit = 0;
+ int accountBuyLimit = 0;
+ for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
+ {
+ attrs = b.getAttributes();
+
+ if ("ingredient".equalsIgnoreCase(b.getNodeName()))
+ {
+ final int ingredientId = parseInteger(attrs, "id");
+ final long ingredientQuantity = parseLong(attrs, "count", 1L);
+ final int ingredientEnchant = parseInteger(attrs, "enchant", 0);
+
+ final Item item = ItemTable.getInstance().getTemplate(ingredientId);
+ if (item == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Item template null for itemId: " + productionId + " productId: " + id);
+ continue;
+ }
+
+ if (ingredientIds[0] == 0)
+ {
+ ingredientIds[0] = ingredientId;
+ }
+ else if (ingredientIds[1] == 0)
+ {
+ ingredientIds[1] = ingredientId;
+ }
+ else if (ingredientIds[2] == 0)
+ {
+ ingredientIds[2] = ingredientId;
+ }
+ else if (ingredientIds[3] == 0)
+ {
+ ingredientIds[3] = ingredientId;
+ }
+ else
+ {
+ ingredientIds[4] = ingredientId;
+ }
+
+ if (ingredientQuantities[0] == 0)
+ {
+ ingredientQuantities[0] = ingredientQuantity;
+ }
+ else if (ingredientQuantities[1] == 0)
+ {
+ ingredientQuantities[1] = ingredientQuantity;
+ }
+ else if (ingredientQuantities[2] == 0)
+ {
+ ingredientQuantities[2] = ingredientQuantity;
+ }
+ else if (ingredientQuantities[3] == 0)
+ {
+ ingredientQuantities[3] = ingredientQuantity;
+ }
+ else
+ {
+ ingredientQuantities[4] = ingredientQuantity;
+ }
+
+ if (ingredientEnchants[0] == 0)
+ {
+ ingredientEnchants[0] = ingredientEnchant;
+ }
+ else if (ingredientEnchants[1] == 0)
+ {
+ ingredientEnchants[1] = ingredientEnchant;
+ }
+ else if (ingredientEnchants[2] == 0)
+ {
+ ingredientEnchants[2] = ingredientEnchant;
+ }
+ else if (ingredientEnchants[3] == 0)
+ {
+ ingredientEnchants[3] = ingredientEnchant;
+ }
+ else
+ {
+ ingredientEnchants[4] = ingredientEnchant;
+ }
+ }
+ else if ("production".equalsIgnoreCase(b.getNodeName()))
+ {
+ productionId = parseInteger(attrs, "id");
+ count = parseLong(attrs, "count", 1L);
+ chance = parseFloat(attrs, "chance", 100f);
+ productionId2 = parseInteger(attrs, "id2", 0);
+ count2 = parseLong(attrs, "count2", 1L);
+ chance2 = parseFloat(attrs, "chance2", 100f);
+ productionId3 = parseInteger(attrs, "id3", 0);
+ count3 = parseLong(attrs, "count3", 1L);
+ chance3 = parseFloat(attrs, "chance3", 100f);
+ productionId4 = parseInteger(attrs, "id4", 0);
+ count4 = parseLong(attrs, "count4", 1L);
+ chance4 = parseFloat(attrs, "chance4", 100f);
+ productionId5 = parseInteger(attrs, "id5", 0);
+ count5 = parseLong(attrs, "count5", 1L);
+ accountDailyLimit = parseInteger(attrs, "accountDailyLimit", 0);
+ accountBuyLimit = parseInteger(attrs, "accountBuyLimit", 0);
+
+ final Item item = ItemTable.getInstance().getTemplate(productionId);
+ if (item == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Item template null for itemId: " + productionId + " productId: " + id);
+ continue;
+ }
+ }
+ }
+
+ _products.add(new LimitShopProductHolder(id, category, minLevel, maxLevel, ingredientIds, ingredientQuantities, ingredientEnchants, productionId, count, chance, productionId2, count2, chance2, productionId3, count3, chance3, productionId4, count4, chance4, productionId5, count5, accountDailyLimit, accountBuyLimit));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public LimitShopProductHolder getProduct(int id)
+ {
+ for (LimitShopProductHolder product : _products)
+ {
+ if (product.getId() == id)
+ {
+ return product;
+ }
+ }
+ return null;
+ }
+
+ public Collection getProducts()
+ {
+ return _products;
+ }
+
+ public static LimitShopCraftData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final LimitShopCraftData INSTANCE = new LimitShopCraftData();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/data/xml/LimitShopData.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/data/xml/LimitShopData.java
new file mode 100644
index 0000000000..43b16eae41
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/data/xml/LimitShopData.java
@@ -0,0 +1,243 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.data.ItemTable;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.holders.LimitShopProductHolder;
+import org.l2jmobius.gameserver.model.items.Item;
+
+/**
+ * @author Mobius
+ */
+public class LimitShopData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(LimitShopData.class.getName());
+
+ private final List _products = new ArrayList<>();
+
+ protected LimitShopData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _products.clear();
+ parseDatapackFile("data/LimitShop.xml");
+
+ if (!_products.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _products.size() + " items.");
+ }
+ else
+ {
+ LOGGER.info(getClass().getSimpleName() + ": System is disabled.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ final NamedNodeMap at = n.getAttributes();
+ final Node attribute = at.getNamedItem("enabled");
+ if ((attribute != null) && Boolean.parseBoolean(attribute.getNodeValue()))
+ {
+ for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("product".equalsIgnoreCase(d.getNodeName()))
+ {
+ NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ final StatSet set = new StatSet();
+ for (int i = 0; i < attrs.getLength(); i++)
+ {
+ att = attrs.item(i);
+ set.set(att.getNodeName(), att.getNodeValue());
+ }
+
+ final int id = parseInteger(attrs, "id");
+ final int category = parseInteger(attrs, "category");
+ final int minLevel = parseInteger(attrs, "minLevel", 1);
+ final int maxLevel = parseInteger(attrs, "maxLevel", 999);
+ final int[] ingredientIds = new int[5];
+ ingredientIds[0] = 0;
+ ingredientIds[1] = 0;
+ ingredientIds[2] = 0;
+ ingredientIds[3] = 0;
+ ingredientIds[4] = 0;
+ final long[] ingredientQuantities = new long[5];
+ ingredientQuantities[0] = 0;
+ ingredientQuantities[1] = 0;
+ ingredientQuantities[2] = 0;
+ ingredientQuantities[3] = 0;
+ ingredientQuantities[4] = 0;
+ final int[] ingredientEnchants = new int[5];
+ ingredientEnchants[0] = 0;
+ ingredientEnchants[1] = 0;
+ ingredientEnchants[2] = 0;
+ ingredientEnchants[3] = 0;
+ ingredientEnchants[4] = 0;
+ int productionId = 0;
+ int accountDailyLimit = 0;
+ int accountBuyLimit = 0;
+ for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
+ {
+ attrs = b.getAttributes();
+
+ if ("ingredient".equalsIgnoreCase(b.getNodeName()))
+ {
+ final int ingredientId = parseInteger(attrs, "id");
+ final long ingredientQuantity = parseLong(attrs, "count", 1L);
+ final int ingredientEnchant = parseInteger(attrs, "enchant", 0);
+
+ final Item item = ItemTable.getInstance().getTemplate(ingredientId);
+ if (item == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Item template null for itemId: " + productionId + " productId: " + id);
+ continue;
+ }
+
+ if (ingredientIds[0] == 0)
+ {
+ ingredientIds[0] = ingredientId;
+ }
+ else if (ingredientIds[1] == 0)
+ {
+ ingredientIds[1] = ingredientId;
+ }
+ else if (ingredientIds[2] == 0)
+ {
+ ingredientIds[2] = ingredientId;
+ }
+ else if (ingredientIds[3] == 0)
+ {
+ ingredientIds[3] = ingredientId;
+ }
+ else
+ {
+ ingredientIds[4] = ingredientId;
+ }
+
+ if (ingredientQuantities[0] == 0)
+ {
+ ingredientQuantities[0] = ingredientQuantity;
+ }
+ else if (ingredientQuantities[1] == 0)
+ {
+ ingredientQuantities[1] = ingredientQuantity;
+ }
+ else if (ingredientQuantities[2] == 0)
+ {
+ ingredientQuantities[2] = ingredientQuantity;
+ }
+ else if (ingredientQuantities[3] == 0)
+ {
+ ingredientQuantities[3] = ingredientQuantity;
+ }
+ else
+ {
+ ingredientQuantities[4] = ingredientQuantity;
+ }
+
+ if (ingredientEnchants[0] == 0)
+ {
+ ingredientEnchants[0] = ingredientEnchant;
+ }
+ else if (ingredientEnchants[1] == 0)
+ {
+ ingredientEnchants[1] = ingredientEnchant;
+ }
+ else if (ingredientEnchants[2] == 0)
+ {
+ ingredientEnchants[2] = ingredientEnchant;
+ }
+ else if (ingredientEnchants[3] == 0)
+ {
+ ingredientEnchants[3] = ingredientEnchant;
+ }
+ else
+ {
+ ingredientEnchants[4] = ingredientEnchant;
+ }
+ }
+ else if ("production".equalsIgnoreCase(b.getNodeName()))
+ {
+ productionId = parseInteger(attrs, "id");
+ accountDailyLimit = parseInteger(attrs, "accountDailyLimit", 0);
+ accountBuyLimit = parseInteger(attrs, "accountBuyLimit", 0);
+
+ final Item item = ItemTable.getInstance().getTemplate(productionId);
+ if (item == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Item template null for itemId: " + productionId + " productId: " + id);
+ continue;
+ }
+ }
+ }
+
+ _products.add(new LimitShopProductHolder(id, category, minLevel, maxLevel, ingredientIds, ingredientQuantities, ingredientEnchants, productionId, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, accountDailyLimit, accountBuyLimit));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public LimitShopProductHolder getProduct(int id)
+ {
+ for (LimitShopProductHolder product : _products)
+ {
+ if (product.getId() == id)
+ {
+ return product;
+ }
+ }
+ return null;
+ }
+
+ public Collection getProducts()
+ {
+ return _products;
+ }
+
+ public static LimitShopData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final LimitShopData INSTANCE = new LimitShopData();
+ }
+}
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index f353dc140b..f84e4ca430 100644
--- a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -357,6 +357,7 @@ import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExActivateAutoSho
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
+import org.l2jmobius.gameserver.network.serverpackets.limitshop.ExBloodyCoinCount;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
@@ -3457,6 +3458,12 @@ public class PlayerInstance extends Playable
}
}
+ // Einhasad coin UI update.
+ if (destoyedItem.getId() == Inventory.EINHASAD_COIN_ID)
+ {
+ sendPacket(new ExBloodyCoinCount(this));
+ }
+
return true;
}
@@ -3566,6 +3573,12 @@ public class PlayerInstance extends Playable
}
}
+ // Einhasad coin UI update.
+ if (item.getId() == Inventory.EINHASAD_COIN_ID)
+ {
+ sendPacket(new ExBloodyCoinCount(this));
+ }
+
return true;
}
@@ -3634,6 +3647,13 @@ public class PlayerInstance extends Playable
targetPlayer.sendItemList();
}
}
+
+ // Einhasad coin UI update.
+ if (newItem.getId() == Inventory.EINHASAD_COIN_ID)
+ {
+ sendPacket(new ExBloodyCoinCount(this));
+ }
+
return newItem;
}
@@ -3741,6 +3761,12 @@ public class PlayerInstance extends Playable
sendPacket(sm);
}
+ // Einhasad coin UI update.
+ if (item.getId() == Inventory.EINHASAD_COIN_ID)
+ {
+ sendPacket(new ExBloodyCoinCount(this));
+ }
+
return true;
}
@@ -3815,6 +3841,12 @@ public class PlayerInstance extends Playable
sendPacket(sm);
}
+ // Einhasad coin UI update.
+ if (item.getId() == Inventory.EINHASAD_COIN_ID)
+ {
+ sendPacket(new ExBloodyCoinCount(this));
+ }
+
return item;
}
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/holders/LimitShopProductHolder.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/holders/LimitShopProductHolder.java
new file mode 100644
index 0000000000..6f103dedaa
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/holders/LimitShopProductHolder.java
@@ -0,0 +1,189 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author Mobius
+ */
+public class LimitShopProductHolder
+{
+ private final int _id;
+ private final int _category;
+ private final int _minLevel;
+ private final int _maxLevel;
+ private final int[] _ingredientIds;
+ private final long[] _ingredientQuantities;
+ private final int[] _ingredientEnchants;
+ private final int _productionId;
+ private final long _count;
+ private final float _chance;
+ private final int _productionId2;
+ private final long _count2;
+ private final float _chance2;
+ private final int _productionId3;
+ private final long _count3;
+ private final float _chance3;
+ private final int _productionId4;
+ private final long _count4;
+ private final float _chance4;
+ private final int _productionId5;
+ private final long _count5;
+ private final int _accountDailyLimit;
+ private final int _accountBuyLimit;
+
+ public LimitShopProductHolder(int id, int category, int minLevel, int maxLevel, int[] ingredientIds, long[] ingredientQuantities, int[] ingredientEnchants, int productionId, long count, float chance, int productionId2, long count2, float chance2, int productionId3, long count3, float chance3, int productionId4, long count4, float chance4, int productionId5, long count5, int accountDailyLimit, int accountBuyLimit)
+ {
+ _id = id;
+ _category = category;
+ _minLevel = minLevel;
+ _maxLevel = maxLevel;
+ _ingredientIds = ingredientIds;
+ _ingredientQuantities = ingredientQuantities;
+ _ingredientEnchants = ingredientEnchants;
+ _productionId = productionId;
+ _count = count;
+ _chance = chance;
+ _productionId2 = productionId2;
+ _count2 = count2;
+ _chance2 = chance2;
+ _productionId3 = productionId3;
+ _count3 = count3;
+ _chance3 = chance3;
+ _productionId4 = productionId4;
+ _count4 = count4;
+ _chance4 = chance4;
+ _productionId5 = productionId5;
+ _count5 = count5;
+ _accountDailyLimit = accountDailyLimit;
+ _accountBuyLimit = accountBuyLimit;
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getCategory()
+ {
+ return _category;
+ }
+
+ public int getMinLevel()
+ {
+ return _minLevel;
+ }
+
+ public int getMaxLevel()
+ {
+ return _maxLevel;
+ }
+
+ public int[] getIngredientIds()
+ {
+ return _ingredientIds;
+ }
+
+ public long[] getIngredientQuantities()
+ {
+ return _ingredientQuantities;
+ }
+
+ public int[] getIngredientEnchants()
+ {
+ return _ingredientEnchants;
+ }
+
+ public int getProductionId()
+ {
+ return _productionId;
+ }
+
+ public long getCount()
+ {
+ return _count;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public int getProductionId2()
+ {
+ return _productionId2;
+ }
+
+ public long getCount2()
+ {
+ return _count2;
+ }
+
+ public float getChance2()
+ {
+ return _chance2;
+ }
+
+ public int getProductionId3()
+ {
+ return _productionId3;
+ }
+
+ public long getCount3()
+ {
+ return _count3;
+ }
+
+ public float getChance3()
+ {
+ return _chance3;
+ }
+
+ public int getProductionId4()
+ {
+ return _productionId4;
+ }
+
+ public long getCount4()
+ {
+ return _count4;
+ }
+
+ public float getChance4()
+ {
+ return _chance4;
+ }
+
+ public int getProductionId5()
+ {
+ return _productionId5;
+ }
+
+ public long getCount5()
+ {
+ return _count5;
+ }
+
+ public int getAccountDailyLimit()
+ {
+ return _accountDailyLimit;
+ }
+
+ public int getAccountBuyLimit()
+ {
+ return _accountBuyLimit;
+ }
+}
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/holders/LimitShopRandomCraftReward.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/holders/LimitShopRandomCraftReward.java
new file mode 100644
index 0000000000..01567438b3
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/holders/LimitShopRandomCraftReward.java
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author Gustavo Fonseca
+ */
+public class LimitShopRandomCraftReward
+{
+ private final int _itemId;
+ private final int _count;
+ private final int _rewardIndex;
+
+ public LimitShopRandomCraftReward(int itemId, int count, int rewardIndex)
+ {
+ _itemId = itemId;
+ _count = count;
+ _rewardIndex = rewardIndex;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getCount()
+ {
+ return _count;
+ }
+
+ public int getRewardIndex()
+ {
+ return _rewardIndex;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 14cdc84ac1..9d0032a250 100644
--- a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -88,7 +88,7 @@ public abstract class Inventory extends ItemContainer
public static final int AIR_STONE_ID = 39461;
public static final int TEMPEST_STONE_ID = 39592;
public static final int ELCYUM_CRYSTAL_ID = 36514;
-
+ public static final int EINHASAD_COIN_ID = 48472; // Lcoin on Essence.
public static final long MAX_ADENA = Config.MAX_ADENA;
public static final int PAPERDOLL_UNDER = 0;
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbce4c8eea..dbb4b300bd 100644
--- a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -41,6 +41,8 @@ public class AccountVariables extends AbstractVariables
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
+ public static final String LCOIN_SHOP_PRODUCT_TIME = "LCSTime";
+ public static final String LCOIN_SHOP_PRODUCT_COUNT = "LCSCount";
private final String _accountName;
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index c97a47adcc..d895c84b54 100644
--- a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -99,6 +99,8 @@ import org.l2jmobius.gameserver.network.clientpackets.homunculus.RequestExShowHo
import org.l2jmobius.gameserver.network.clientpackets.homunculus.RequestExSummonHomunculusCouponResult;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneEnter;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneList;
+import org.l2jmobius.gameserver.network.clientpackets.limitshop.RequestPurchaseLimitShopItemBuy;
+import org.l2jmobius.gameserver.network.clientpackets.limitshop.RequestPurchaseLimitShopItemList;
import org.l2jmobius.gameserver.network.clientpackets.luckygame.RequestLuckyGamePlay;
import org.l2jmobius.gameserver.network.clientpackets.luckygame.RequestLuckyGameStartInfo;
import org.l2jmobius.gameserver.network.clientpackets.mentoring.ConfirmMenteeAdd;
@@ -505,8 +507,8 @@ public enum ExIncomingPackets implements IIncomingPackets
EX_INTERACT_MODIFY(0x15F, null, ConnectionState.IN_GAME),
EX_TRY_ENCHANT_ARTIFACT(0x160, RequestExTryEnchantArtifact::new, ConnectionState.IN_GAME),
EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, null, ConnectionState.IN_GAME),
- EX_PURCHASE_LIMIT_SHOP_ITEM_LIST(0x162, null, ConnectionState.IN_GAME),
- EX_PURCHASE_LIMIT_SHOP_ITEM_BUY(0x163, null, ConnectionState.IN_GAME),
+ EX_PURCHASE_LIMIT_SHOP_ITEM_LIST(0x162, RequestPurchaseLimitShopItemList::new, ConnectionState.IN_GAME),
+ EX_PURCHASE_LIMIT_SHOP_ITEM_BUY(0x163, RequestPurchaseLimitShopItemBuy::new, ConnectionState.IN_GAME),
// 228
EX_OPEN_HTML(0x164, ExOpenHtml::new, ConnectionState.IN_GAME),
EX_REQUEST_CLASS_CHANGE(0x165, ExRequestClassChange::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
new file mode 100644
index 0000000000..bbfb144b24
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
@@ -0,0 +1,266 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.limitshop;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Chronos;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.LimitShopCraftData;
+import org.l2jmobius.gameserver.data.xml.LimitShopData;
+import org.l2jmobius.gameserver.enums.SpecialItemType;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
+import org.l2jmobius.gameserver.model.holders.LimitShopProductHolder;
+import org.l2jmobius.gameserver.model.holders.LimitShopRandomCraftReward;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.limitshop.ExPurchaseLimitShopItemResult;
+import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
+import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct.ExBrProductReplyType;
+
+/**
+ * @author Mobius
+ */
+public class RequestPurchaseLimitShopItemBuy implements IClientIncomingPacket
+{
+ private int _productId;
+ private int _amount;
+ private LimitShopProductHolder _product;
+ private int _shopIndex;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _shopIndex = packet.readC(); // 3 Lcoin Store, 4 Special Craft, 100 Clan Shop
+ _productId = packet.readD();
+ _amount = packet.readD();
+
+ switch (_shopIndex)
+ {
+ case 3: // Normal Lcoin Shop
+ {
+ _product = LimitShopData.getInstance().getProduct(_productId);
+ break;
+ }
+ case 4: // Lcoin Special Craft
+ {
+ _product = LimitShopCraftData.getInstance().getProduct(_productId);
+ break;
+ }
+ default:
+ {
+ _product = null;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (_amount < 1)
+ {
+ return;
+ }
+
+ if (_product == null)
+ {
+ return;
+ }
+
+ if ((player.getLevel() < _product.getMinLevel()) || (player.getLevel() > _product.getMaxLevel()))
+ {
+ player.sendPacket(SystemMessageId.YOUR_LEVEL_CANNOT_PURCHASE_THIS_ITEM);
+ return;
+ }
+
+ if (player.hasItemRequest() || player.hasRequest(PrimeShopRequest.class))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.INVALID_USER_STATE));
+ return;
+ }
+
+ // Add request.
+ player.addRequest(new PrimeShopRequest(player));
+
+ // Check limits.
+ if (_product.getAccountDailyLimit() > 0) // Sale period.
+ {
+ if (player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + _product.getProductionId(), 0) >= (_product.getAccountDailyLimit() * _amount))
+ {
+ if ((player.getAccountVariables().getLong(AccountVariables.LCOIN_SHOP_PRODUCT_TIME + _product.getProductionId(), 0) + 86400000) > Chronos.currentTimeMillis())
+ {
+ player.sendMessage("You have reached your daily limit."); // TODO: Retail system message?
+ player.removeRequest(PrimeShopRequest.class);
+ return;
+ }
+ // Reset limit.
+ player.getAccountVariables().set(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + _product.getProductionId(), 0);
+ }
+ }
+ else if (_product.getAccountBuyLimit() > 0) // Count limit.
+ {
+ if (player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + _product.getProductionId(), 0) >= (_product.getAccountBuyLimit() * _amount))
+ {
+ player.sendMessage("You cannot buy any more of this item."); // TODO: Retail system message?
+ player.removeRequest(PrimeShopRequest.class);
+ return;
+ }
+ }
+
+ // Check existing items.
+ for (int i = 0; i < 3; i++)
+ {
+ if (_product.getIngredientIds()[i] == 0)
+ {
+ continue;
+ }
+ if (_product.getIngredientIds()[i] == Inventory.ADENA_ID)
+ {
+ if (player.getAdena() < (_product.getIngredientQuantities()[i] * _amount))
+ {
+ player.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT_2);
+ player.removeRequest(PrimeShopRequest.class);
+ return;
+ }
+ }
+ else if (_product.getIngredientIds()[i] == SpecialItemType.HONOR_COINS.getClientId())
+ {
+ if (player.getHonorCoins() < (_product.getIngredientQuantities()[i] * _amount))
+ {
+ player.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT_2);
+ player.removeRequest(PrimeShopRequest.class);
+ return;
+ }
+ }
+ else if (player.getInventory().getInventoryItemCount(_product.getIngredientIds()[i], _product.getIngredientEnchants()[i] == 0 ? -1 : _product.getIngredientEnchants()[i], true) < (_product.getIngredientQuantities()[i] * _amount))
+ {
+ player.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT_2);
+ player.removeRequest(PrimeShopRequest.class);
+ return;
+ }
+ }
+
+ // Remove items.
+ for (int i = 0; i < 3; i++)
+ {
+ if (_product.getIngredientIds()[i] == 0)
+ {
+ continue;
+ }
+ if (_product.getIngredientIds()[i] == Inventory.ADENA_ID)
+ {
+ player.reduceAdena("LCoinShop", _product.getIngredientQuantities()[i] * _amount, player, true);
+ }
+ else if (_product.getIngredientIds()[i] == SpecialItemType.HONOR_COINS.getClientId())
+ {
+ player.setHonorCoins(player.getHonorCoins() - (_product.getIngredientQuantities()[i] * _amount));
+ }
+ else
+ {
+ if (_product.getIngredientEnchants()[i] > 0)
+ {
+ int count = 0;
+ final Collection items = player.getInventory().getAllItemsByItemId(_product.getIngredientIds()[i], _product.getIngredientEnchants()[i]);
+ for (ItemInstance item : items)
+ {
+ if (count == _amount)
+ {
+ break;
+ }
+ count++;
+ player.destroyItem("LCoinShop", item, player, true);
+ }
+ }
+ else
+ {
+ player.destroyItemByItemId("LCoinShop", _product.getIngredientIds()[i], _product.getIngredientQuantities()[i] * _amount, player, true);
+ }
+ }
+ }
+
+ // Reward.
+ final List rewards = new ArrayList<>();
+ if (_product.getProductionId2() > 0)
+ {
+ for (int i = 0; i < _amount; i++)
+ {
+ if (Rnd.get(100) < _product.getChance())
+ {
+ rewards.add(new LimitShopRandomCraftReward(_product.getProductionId(), (int) _product.getCount(), 0));
+ player.addItem("LCoinShop", _product.getProductionId(), _product.getCount(), player, true);
+ }
+ else if (Rnd.get(100) < _product.getChance2())
+ {
+ rewards.add(new LimitShopRandomCraftReward(_product.getProductionId2(), (int) _product.getCount2(), 1));
+ player.addItem("LCoinShop", _product.getProductionId2(), _product.getCount2(), player, true);
+ }
+ else if (Rnd.get(100) < _product.getChance3())
+ {
+ rewards.add(new LimitShopRandomCraftReward(_product.getProductionId3(), (int) _product.getCount3(), 2));
+ player.addItem("LCoinShop", _product.getProductionId3(), _product.getCount3(), player, true);
+ }
+ else if (Rnd.get(100) < _product.getChance4())
+ {
+ rewards.add(new LimitShopRandomCraftReward(_product.getProductionId4(), (int) _product.getCount4(), 3));
+ player.addItem("LCoinShop", _product.getProductionId4(), _product.getCount4(), player, true);
+ }
+ else if (_product.getProductionId5() > 0)
+ {
+ rewards.add(new LimitShopRandomCraftReward(_product.getProductionId5(), (int) _product.getCount5(), 4));
+ player.addItem("LCoinShop", _product.getProductionId5(), _product.getCount5(), player, true);
+ }
+ }
+ }
+ else
+ {
+ rewards.add(new LimitShopRandomCraftReward(_product.getProductionId(), _amount, 0));
+ player.addItem("LCoinShop", _product.getProductionId(), _amount, player, true);
+ }
+
+ // Update account variables.
+ if (_product.getAccountDailyLimit() > 0)
+ {
+ player.getAccountVariables().set(AccountVariables.LCOIN_SHOP_PRODUCT_TIME + _product.getProductionId(), Chronos.currentTimeMillis());
+ player.getAccountVariables().set(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + _product.getProductionId(), player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + _product.getProductionId(), 0) + _amount);
+ }
+ else if (_product.getAccountBuyLimit() > 0)
+ {
+ player.getAccountVariables().set(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + _product.getProductionId(), player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + _product.getProductionId(), 0) + _amount);
+ }
+
+ player.sendPacket(new ExPurchaseLimitShopItemResult(true, _shopIndex, _productId, rewards));
+
+ // Remove request.
+ player.removeRequest(PrimeShopRequest.class);
+ }
+}
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemList.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemList.java
new file mode 100644
index 0000000000..2cf980beb7
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemList.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.limitshop;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.limitshop.ExPurchaseLimitShopItemListNew;
+
+/**
+ * @author Mobius
+ */
+public class RequestPurchaseLimitShopItemList implements IClientIncomingPacket
+{
+ private int _category;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _category = packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new ExPurchaseLimitShopItemListNew(_category, player));
+ }
+}
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExBloodyCoinCount.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExBloodyCoinCount.java
new file mode 100644
index 0000000000..276634c972
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExBloodyCoinCount.java
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.limitshop;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExBloodyCoinCount implements IClientOutgoingPacket
+{
+ private final long _count;
+
+ public ExBloodyCoinCount(PlayerInstance player)
+ {
+ _count = player.getInventory().getInventoryItemCount(Inventory.EINHASAD_COIN_ID, -1);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BLOODY_COIN_COUNT.writeId(packet);
+ packet.writeQ(_count);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExPurchaseLimitShopItemListNew.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExPurchaseLimitShopItemListNew.java
new file mode 100644
index 0000000000..7170bbea55
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExPurchaseLimitShopItemListNew.java
@@ -0,0 +1,136 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.limitshop;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.commons.util.Chronos;
+import org.l2jmobius.gameserver.data.xml.LimitShopCraftData;
+import org.l2jmobius.gameserver.data.xml.LimitShopData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.LimitShopProductHolder;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExPurchaseLimitShopItemListNew implements IClientOutgoingPacket
+{
+ private final int _shopType; // 3 Lcoin Store, 4 Special Craft, 100 Clan Shop
+ private final PlayerInstance _player;
+ private final Collection _products;
+
+ public ExPurchaseLimitShopItemListNew(int shopType, PlayerInstance player)
+ {
+ _shopType = shopType;
+ _player = player;
+
+ switch (shopType)
+ {
+ case 3: // Normal Lcoin Shop
+ {
+ _products = LimitShopData.getInstance().getProducts();
+ break;
+ }
+ case 4: // Lcoin Special Craft
+ {
+ _products = LimitShopCraftData.getInstance().getProducts();
+ break;
+ }
+ default:
+ {
+ _products = Collections.emptyList();
+ }
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_PURCHASE_LIMIT_SHOP_ITEM_LIST_NEW.writeId(packet);
+
+ packet.writeC(_shopType);
+ packet.writeC(0x01); // Page. (311)
+ packet.writeC(0x01); // MaxPage. (311)
+ packet.writeD(_products.size());
+ for (LimitShopProductHolder product : _products)
+ {
+ packet.writeD(product.getId());
+ packet.writeD(product.getProductionId());
+ packet.writeD(product.getIngredientIds()[0]);
+ packet.writeD(product.getIngredientIds()[1]);
+ packet.writeD(product.getIngredientIds()[2]);
+ packet.writeD(product.getIngredientIds()[3]); // 306
+ packet.writeD(product.getIngredientIds()[4]); // 306
+ packet.writeQ(product.getIngredientQuantities()[0]);
+ packet.writeQ(product.getIngredientQuantities()[1]);
+ packet.writeQ(product.getIngredientQuantities()[2]);
+ packet.writeQ(product.getIngredientQuantities()[3]); // 306
+ packet.writeQ(product.getIngredientQuantities()[4]); // 306
+ packet.writeH(product.getIngredientEnchants()[0]);
+ packet.writeH(product.getIngredientEnchants()[1]);
+ packet.writeH(product.getIngredientEnchants()[2]);
+ packet.writeH(product.getIngredientEnchants()[3]); // 306
+ packet.writeH(product.getIngredientEnchants()[4]); // 306
+
+ // Check limits.
+ if (product.getAccountDailyLimit() > 0) // Sale period.
+ {
+ if (_player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + product.getProductionId(), 0) >= product.getAccountDailyLimit())
+ {
+ if ((_player.getAccountVariables().getLong(AccountVariables.LCOIN_SHOP_PRODUCT_TIME + product.getProductionId(), 0) + 86400000) > Chronos.currentTimeMillis())
+ {
+ packet.writeD(0x00);
+ }
+ else // Reset limit.
+ {
+ _player.getAccountVariables().remove(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + product.getProductionId());
+ packet.writeD(product.getAccountDailyLimit());
+ }
+ }
+ else
+ {
+ packet.writeD(product.getAccountDailyLimit() - _player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + product.getProductionId(), 0));
+ }
+ }
+ else if (product.getAccountBuyLimit() > 0) // Count limit.
+ {
+ if (_player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + product.getProductionId(), 0) >= product.getAccountBuyLimit())
+ {
+ packet.writeD(0x00);
+ }
+ else
+ {
+ packet.writeD(product.getAccountBuyLimit() - _player.getAccountVariables().getInt(AccountVariables.LCOIN_SHOP_PRODUCT_COUNT + product.getProductionId(), 0));
+ }
+ }
+ else // No account limits.
+ {
+ packet.writeD(0x01);
+ }
+ packet.writeD(0x00); // nRemainSec
+ packet.writeD(0x00); // nRemainServerItemAmount
+ packet.writeH(0x00); // sCircleNum (311)
+ }
+
+ return true;
+ }
+}
diff --git a/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExPurchaseLimitShopItemResult.java b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExPurchaseLimitShopItemResult.java
new file mode 100644
index 0000000000..e4ee346643
--- /dev/null
+++ b/L2J_Mobius_10.0_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/limitshop/ExPurchaseLimitShopItemResult.java
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.limitshop;
+
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.LimitShopCraftData;
+import org.l2jmobius.gameserver.data.xml.LimitShopData;
+import org.l2jmobius.gameserver.model.holders.LimitShopProductHolder;
+import org.l2jmobius.gameserver.model.holders.LimitShopRandomCraftReward;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gustavo Fonseca
+ */
+public class ExPurchaseLimitShopItemResult implements IClientOutgoingPacket
+{
+ private final int _category, _productId;
+ private final boolean _isSuccess;
+ private final List _rewards;
+ private final LimitShopProductHolder _product;
+
+ public ExPurchaseLimitShopItemResult(boolean isSuccess, int category, int productId, List rewards)
+ {
+ _isSuccess = isSuccess;
+ _category = category;
+ _productId = productId;
+ _rewards = rewards;
+
+ switch (_category)
+ {
+ case 3: // Normal Lcoin Shop
+ {
+ _product = LimitShopData.getInstance().getProduct(_productId);
+ break;
+ }
+ case 4: // Lcoin Special Craft
+ {
+ _product = LimitShopCraftData.getInstance().getProduct(_productId);
+ break;
+ }
+ default:
+ {
+ _product = null;
+ }
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_PURCHASE_LIMIT_SHOP_ITEM_BUY.writeId(packet);
+ if ((_product == null) || !_isSuccess)
+ {
+ packet.writeC(1);
+ packet.writeC(_category);
+ packet.writeD(_productId);
+ packet.writeD(1);
+ packet.writeC(1);
+ packet.writeD(0);
+ packet.writeQ(0);
+ }
+ else
+ {
+ packet.writeC(0); // success
+ packet.writeC(_category);
+ packet.writeD(_productId);
+ packet.writeD(_rewards.size());
+ int counter = 0;
+ for (LimitShopRandomCraftReward entry : _rewards)
+ {
+ if (counter == _rewards.size())
+ {
+ break;
+ }
+ packet.writeC(entry.getRewardIndex());
+ packet.writeD(0);
+ packet.writeD(entry.getCount());
+ counter++;
+ }
+ }
+ return true;
+ }
+}
\ No newline at end of file