diff --git a/L2J_Mobius_08.2_Homunculus/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_08.2_Homunculus/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..42e12e3913
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_08.2_Homunculus/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_08.2_Homunculus/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index adf66d2a8a..b6bbe8745a 100644
--- a/L2J_Mobius_08.2_Homunculus/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_08.2_Homunculus/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -204,6 +204,13 @@ public class GameAssistant extends AbstractNpcAI
}
break;
}
+ case "items_conversion":
+ {
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
+ break;
+ }
}
return htmltext;
}
diff --git a/L2J_Mobius_08.2_Homunculus/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_08.2_Homunculus/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/GameServer.java
index abca4f26e2..a7480b8f65 100644
--- a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/GameServer.java
@@ -69,6 +69,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -278,6 +279,7 @@ public class GameServer
BuyListData.getInstance();
MultisellData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RecipeData.getInstance();
ArmorSetData.getInstance();
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index d464a7ffa3..2881b6b8a2 100644
--- a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -75,6 +75,7 @@ import org.l2jmobius.gameserver.network.clientpackets.crystalization.RequestCrys
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.faction.RequestUserFactionInfo;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.homunculus.ExHomunculusEvolve;
@@ -498,7 +499,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
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_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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),
// 228
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..42e12e3913
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index adf66d2a8a..b6bbe8745a 100644
--- a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -204,6 +204,13 @@ public class GameAssistant extends AbstractNpcAI
}
break;
}
+ case "items_conversion":
+ {
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
+ break;
+ }
}
return htmltext;
}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
index 0c22a7dc5e..f9bc4d9e6e 100644
--- a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
@@ -1,6 +1,6 @@
-
+
@@ -98,7 +98,7 @@
-
+
@@ -197,7 +197,7 @@
-
+
@@ -281,7 +281,7 @@
-
+
@@ -366,7 +366,7 @@
-
+
@@ -467,7 +467,7 @@
-
+
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java
index 5357aec0e6..9801eed16a 100644
--- a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/GameServer.java
@@ -70,6 +70,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -280,6 +281,7 @@ public class GameServer
BuyListData.getInstance();
MultisellData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RecipeData.getInstance();
ArmorSetData.getInstance();
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index c885afc1c8..3c8f43814a 100644
--- a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -83,6 +83,7 @@ import org.l2jmobius.gameserver.network.clientpackets.crystalization.RequestCrys
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.faction.RequestUserFactionInfo;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.homunculus.ExHomunculusEvolve;
@@ -508,7 +509,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
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_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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),
// 228
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_10.1_MasterClass/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..42e12e3913
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index d50a94911b..dc5ada5d1e 100644
--- a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -200,6 +200,13 @@ public class GameAssistant extends AbstractNpcAI
}
break;
}
+ case "items_conversion":
+ {
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
+ break;
+ }
}
return htmltext;
}
diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml b/L2J_Mobius_10.1_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
index 0c22a7dc5e..f9bc4d9e6e 100644
--- a/L2J_Mobius_10.1_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
+++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
@@ -1,6 +1,6 @@
-
+
@@ -98,7 +98,7 @@
-
+
@@ -197,7 +197,7 @@
-
+
@@ -281,7 +281,7 @@
-
+
@@ -366,7 +366,7 @@
-
+
@@ -467,7 +467,7 @@
-
+
diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_10.1_MasterClass/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
index 29dae8dc2e..9a1ac5497e 100644
--- a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
@@ -70,6 +70,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -282,6 +283,7 @@ public class GameServer
BuyListData.getInstance();
MultisellData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RecipeData.getInstance();
ArmorSetData.getInstance();
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 66eb7b8124..1a7c9c2e43 100644
--- a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -83,6 +83,7 @@ import org.l2jmobius.gameserver.network.clientpackets.crystalization.RequestCrys
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.faction.RequestUserFactionInfo;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.homunculus.ExHomunculusEvolve;
@@ -510,7 +511,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
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_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_10.2_MasterClass/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..42e12e3913
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index d50a94911b..dc5ada5d1e 100644
--- a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -200,6 +200,13 @@ public class GameAssistant extends AbstractNpcAI
}
break;
}
+ case "items_conversion":
+ {
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
+ break;
+ }
}
return htmltext;
}
diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml b/L2J_Mobius_10.2_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
index 0c22a7dc5e..f9bc4d9e6e 100644
--- a/L2J_Mobius_10.2_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
+++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/spawns/LimitedZones/OutwordlyAtelia.xml
@@ -1,6 +1,6 @@
-
+
@@ -98,7 +98,7 @@
-
+
@@ -197,7 +197,7 @@
-
+
@@ -281,7 +281,7 @@
-
+
@@ -366,7 +366,7 @@
-
+
@@ -467,7 +467,7 @@
-
+
diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_10.2_MasterClass/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
index 29dae8dc2e..9a1ac5497e 100644
--- a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/GameServer.java
@@ -70,6 +70,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -282,6 +283,7 @@ public class GameServer
BuyListData.getInstance();
MultisellData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RecipeData.getInstance();
ArmorSetData.getInstance();
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index c8ac877e00..682088613c 100644
--- a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -94,6 +94,7 @@ import org.l2jmobius.gameserver.network.clientpackets.enchant.single.ExRequestVi
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.faction.RequestUserFactionInfo;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.homunculus.ExHomunculusEvolve;
@@ -528,7 +529,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
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_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..8490183c06
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index f14df032ed..0fe4e9fb19 100644
--- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -37,7 +37,6 @@ import org.l2jmobius.gameserver.network.serverpackets.PackageToList;
import org.l2jmobius.gameserver.network.serverpackets.WareHouseWithdrawalList;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulExtractionWindow;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulWindow;
-import org.l2jmobius.gameserver.network.serverpackets.equipmentupgrade.ExShowUpgradeSystem;
import ai.AbstractNpcAI;
@@ -277,8 +276,9 @@ public class GameAssistant extends AbstractNpcAI
}
case "items_conversion":
{
- player.setTarget(player);
- player.sendPacket(new ExShowUpgradeSystem());
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
break;
}
// Multisell
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java
index abed6ed15b..899113c596 100644
--- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java
@@ -69,6 +69,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -286,6 +287,7 @@ public class GameServer
BuyListData.getInstance();
MultisellData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RaidTeleportListData.getInstance();
RecipeData.getInstance();
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 2afb87384d..928ac8b247 100644
--- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -77,6 +77,7 @@ import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElement
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneEnter;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneList;
@@ -496,7 +497,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
EX_INTERACT_MODIFY(0x15F, null, ConnectionState.IN_GAME),
EX_TRY_ENCHANT_ARTIFACT(0x160, null, ConnectionState.IN_GAME),
- EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, null, ConnectionState.IN_GAME),
+ EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..de8c2902d5
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,444 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index f3f586bddb..34b9c116c1 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -37,7 +37,6 @@ import org.l2jmobius.gameserver.network.serverpackets.PackageToList;
import org.l2jmobius.gameserver.network.serverpackets.WareHouseWithdrawalList;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulExtractionWindow;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulWindow;
-import org.l2jmobius.gameserver.network.serverpackets.equipmentupgrade.ExShowUpgradeSystem;
import ai.AbstractNpcAI;
@@ -220,8 +219,9 @@ public class GameAssistant extends AbstractNpcAI
}
case "items_conversion":
{
- player.setTarget(player);
- player.sendPacket(new ExShowUpgradeSystem());
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
break;
}
// Multisell
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java
index d42e352b01..d66ac30910 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java
@@ -70,6 +70,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -294,6 +295,7 @@ public class GameServer
BuyListData.getInstance();
MultisellData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RaidTeleportListData.getInstance();
RecipeData.getInstance();
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 49d1bb563f..c6bf1ad710 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -84,6 +84,7 @@ import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElement
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneEnter;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneList;
@@ -519,7 +520,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
EX_INTERACT_MODIFY(0x15F, null, ConnectionState.IN_GAME),
EX_TRY_ENCHANT_ARTIFACT(0x160, null, ConnectionState.IN_GAME),
- EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, null, ConnectionState.IN_GAME),
+ EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..87e5f0c074
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,453 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index a84ec9e869..46fd1e81d3 100644
--- a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -38,7 +38,6 @@ import org.l2jmobius.gameserver.network.serverpackets.PackageToList;
import org.l2jmobius.gameserver.network.serverpackets.WareHouseWithdrawalList;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulExtractionWindow;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulWindow;
-import org.l2jmobius.gameserver.network.serverpackets.equipmentupgrade.ExShowUpgradeSystem;
import ai.AbstractNpcAI;
@@ -238,8 +237,9 @@ public class GameAssistant extends AbstractNpcAI
}
case "items_conversion":
{
- player.setTarget(player);
- player.sendPacket(new ExShowUpgradeSystem());
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
break;
}
// Multisell
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/GameServer.java
index 3b4756850c..c27dc0a923 100644
--- a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/GameServer.java
@@ -71,6 +71,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -296,6 +297,7 @@ public class GameServer
CombinationItemsData.getInstance();
CombinationDyeData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RaidTeleportListData.getInstance();
RecipeData.getInstance();
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 54f3e56d20..c12961eb42 100644
--- a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -85,6 +85,7 @@ import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElement
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneEnter;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneList;
@@ -531,7 +532,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
EX_INTERACT_MODIFY(0x15F, null, ConnectionState.IN_GAME),
EX_TRY_ENCHANT_ARTIFACT(0x160, null, ConnectionState.IN_GAME),
- EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, null, ConnectionState.IN_GAME),
+ EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/EquipmentUpgradeNormalData.xml b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/EquipmentUpgradeNormalData.xml
new file mode 100644
index 0000000000..87e5f0c074
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/EquipmentUpgradeNormalData.xml
@@ -0,0 +1,453 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
index 69f516bc3d..98811197dd 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/others/GameAssistant/GameAssistant.java
@@ -37,7 +37,6 @@ import org.l2jmobius.gameserver.network.serverpackets.PackageToList;
import org.l2jmobius.gameserver.network.serverpackets.WareHouseWithdrawalList;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulExtractionWindow;
import org.l2jmobius.gameserver.network.serverpackets.ensoul.ExShowEnsoulWindow;
-import org.l2jmobius.gameserver.network.serverpackets.equipmentupgrade.ExShowUpgradeSystem;
import org.l2jmobius.gameserver.network.serverpackets.variation.ExShowVariationCancelWindow;
import ai.AbstractNpcAI;
@@ -238,8 +237,9 @@ public class GameAssistant extends AbstractNpcAI
}
case "items_conversion":
{
- player.setTarget(player);
- player.sendPacket(new ExShowUpgradeSystem());
+ // TODO: Add to html.
+ // player.setTarget(player);
+ // player.sendPacket(new ExShowUpgradeSystemNormal(1, 1));
break;
}
// Multisell
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
new file mode 100644
index 0000000000..8bbd82753f
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/xsd/EquipmentUpgradeNormalData.xsd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java
index 3b4756850c..c27dc0a923 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java
@@ -71,6 +71,7 @@ import org.l2jmobius.gameserver.data.xml.EnchantItemOptionsData;
import org.l2jmobius.gameserver.data.xml.EnchantSkillGroupsData;
import org.l2jmobius.gameserver.data.xml.EnsoulData;
import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeData;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
import org.l2jmobius.gameserver.data.xml.ExperienceData;
import org.l2jmobius.gameserver.data.xml.FakePlayerData;
import org.l2jmobius.gameserver.data.xml.FenceData;
@@ -296,6 +297,7 @@ public class GameServer
CombinationItemsData.getInstance();
CombinationDyeData.getInstance();
EquipmentUpgradeData.getInstance();
+ EquipmentUpgradeNormalData.getInstance();
AgathionData.getInstance();
RaidTeleportListData.getInstance();
RecipeData.getInstance();
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
new file mode 100644
index 0000000000..5d5902a480
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/data/xml/EquipmentUpgradeNormalData.java
@@ -0,0 +1,180 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class EquipmentUpgradeNormalData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(EquipmentUpgradeNormalData.class.getName());
+ private static final Map _upgrades = new HashMap<>();
+ private static final Set _discount = new HashSet<>();
+ private static int _commission;
+
+ protected EquipmentUpgradeNormalData()
+ {
+ load();
+ }
+
+ public void reload()
+ {
+ for (Player player : World.getInstance().getPlayers())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _commission = -1;
+ _discount.clear();
+ _upgrades.clear();
+ parseDatapackFile("data/EquipmentUpgradeNormalData.xml");
+ if (!_upgrades.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _upgrades.size() + " upgrade-normal equipment data. Adena commission is " + _commission + ".");
+ }
+ if (!_discount.isEmpty())
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _discount.size() + " upgrade-normal discount data.");
+ }
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", listNode -> forEach(listNode, "params", paramNode -> _commission = new StatSet(parseAttributes(paramNode)).getInt("commission")));
+ if (_commission < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": Commission in file EquipmentUpgradeNormalData.xml not set or less than 0! Setting up default value - 100!");
+ _commission = 100;
+ }
+ forEach(doc, "list", listNode -> forEach(listNode, "discount", discountNode -> forEach(discountNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ _discount.add(new ItemHolder(successSet.getInt("id"), successSet.getLong("count")));
+ })));
+ forEach(doc, "list", listNode -> forEach(listNode, "upgrade", upgradeNode ->
+ {
+ final AtomicReference initialItem = new AtomicReference<>();
+ final AtomicReference> materialItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onSuccessItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> onFailureItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference> bonusItems = new AtomicReference<>(new ArrayList<>());
+ final AtomicReference bonusChance = new AtomicReference<>();
+ final StatSet headerSet = new StatSet(parseAttributes(upgradeNode));
+ final int id = headerSet.getInt("id");
+ final int type = headerSet.getInt("type");
+ final double chance = headerSet.getDouble("chance");
+ final long commission = _commission == 0 ? 0 : ((headerSet.getLong("commission") / 100) * _commission);
+ forEach(upgradeNode, "upgradeItem", upgradeItemNode ->
+ {
+ final StatSet initialSet = new StatSet(parseAttributes(upgradeItemNode));
+ initialItem.set(new ItemEnchantHolder(initialSet.getInt("id"), initialSet.getLong("count"), initialSet.getByte("enchantLevel")));
+ if (initialItem.get() == null)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " seems like broken!");
+ }
+ if (initialItem.get().getCount() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": upgradeItem -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ });
+ forEach(upgradeNode, "material", materialItemNode -> forEach(materialItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ materialItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ // {
+ // LOGGER.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + id +" cant be less than 0!");
+ // }
+ }));
+ forEach(upgradeNode, "successItems", successItemNode -> forEach(successItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onSuccessItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "failure_items", failureItemNode -> forEach(failureItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ onFailureItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ }));
+ forEach(upgradeNode, "bonus_items", bonusItemNode ->
+ {
+ bonusChance.set(new StatSet(parseAttributes(bonusItemNode)).getDouble("chance"));
+ if (bonusChance.get() < 0)
+ {
+ LOGGER.warning(getClass().getSimpleName() + ": bonus_items -> chance in file EquipmentUpgradeNormalData.xml for upgrade id " + id + " cant be less than 0!");
+ }
+ forEach(bonusItemNode, "item", itemNode ->
+ {
+ final StatSet successSet = new StatSet(parseAttributes(itemNode));
+ bonusItems.get().add(new ItemEnchantHolder(successSet.getInt("id"), successSet.getLong("count"), successSet.getInt("enchantLevel")));
+ });
+ });
+ _upgrades.put(id, new EquipmentUpgradeNormalHolder(id, type, commission, chance, initialItem.get(), materialItems.get(), onSuccessItems.get(), onFailureItems.get(), bonusChance.get() == null ? 0 : bonusChance.get(), bonusItems.get()));
+ }));
+ }
+
+ public EquipmentUpgradeNormalHolder getUpgrade(int id)
+ {
+ return _upgrades.get(id);
+ }
+
+ public Set getDiscount()
+ {
+ return _discount;
+ }
+
+ public int getCommission()
+ {
+ return _commission;
+ }
+
+ public static EquipmentUpgradeNormalData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final EquipmentUpgradeNormalData INSTANCE = new EquipmentUpgradeNormalData();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
new file mode 100644
index 0000000000..e2d094dca7
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/UpgradeDataType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.enums;
+
+public enum UpgradeDataType
+{
+ MATERIAL,
+ ON_SUCCESS,
+ ON_FAILURE,
+ BONUS_TYPE;
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
new file mode 100644
index 0000000000..6d57a662c2
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/EquipmentUpgradeNormalHolder.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+
+public class EquipmentUpgradeNormalHolder
+{
+ private final int _id;
+ private final int _type;
+ private final long _commission;
+ private final double _chance;
+ private final ItemEnchantHolder _initialItem;
+ private final double _chanceToReceiveBonusItems;
+ private final Map> _items = new HashMap<>();
+
+ /**
+ * @implNote Holder for "UpgradeNormal" equipment system;
+ * Final Holder will be have getter getItems which get UpgradeDataType;
+ * Don't forget to check in isHasCategory category type in getItems, for don`t get null or empty collections;
+ * @param id Upgrade ID in DAT file; (yep, duplication);
+ * @param type Upgrade type in DAT file (1 / 2 (used in classic);
+ * @param commission Default Adena count, needed for make "Transformation";
+ * @param chance Success chance of made "Transformation";
+ * @param initialItem Item for upgrade; (cannot be empty)
+ * @param materialItems Materials for upgrade; (can be empty)
+ * @param onSuccessItems Items, which player gets if RND will be < chance (if win);
+ * @param onFailureItems Items, which player gets if RND will be > chance (if lose);
+ * @param chanceToReceiveBonusItems Chance to obtain additional reward on Success (if win);
+ * @param bonusItems Bonus Items;
+ */
+ public EquipmentUpgradeNormalHolder(int id, int type, long commission, double chance, ItemEnchantHolder initialItem, List materialItems, List onSuccessItems, List onFailureItems, double chanceToReceiveBonusItems, List bonusItems)
+ {
+ _id = id;
+ _type = type;
+ _commission = commission;
+ _chance = chance;
+ _initialItem = initialItem;
+ _chanceToReceiveBonusItems = chanceToReceiveBonusItems;
+ if (materialItems != null)
+ {
+ _items.put(UpgradeDataType.MATERIAL, materialItems);
+ }
+ _items.put(UpgradeDataType.ON_SUCCESS, onSuccessItems);
+ if (onFailureItems != null)
+ {
+ _items.put(UpgradeDataType.ON_FAILURE, onFailureItems);
+ }
+ if (bonusItems != null)
+ {
+ _items.put(UpgradeDataType.BONUS_TYPE, bonusItems);
+ }
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getType()
+ {
+ return _type;
+ }
+
+ public long getCommission()
+ {
+ return _commission;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public ItemEnchantHolder getInitialItem()
+ {
+ return _initialItem;
+ }
+
+ public double getChanceToReceiveBonusItems()
+ {
+ return _chanceToReceiveBonusItems;
+ }
+
+ public List getItems(UpgradeDataType upgradeDataType)
+ {
+ return _items.get(upgradeDataType);
+ }
+
+ public boolean isHasCategory(UpgradeDataType upgradeDataType)
+ {
+ if (_items.isEmpty())
+ {
+ return false;
+ }
+ return _items.containsKey(upgradeDataType);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
new file mode 100644
index 0000000000..cd394f6bdb
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/ItemEnchantHolder.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.StatSet;
+
+/**
+ * @author Index, Mobius
+ */
+public class ItemEnchantHolder extends ItemHolder
+{
+ private final int _enchantLevel;
+
+ public ItemEnchantHolder(StatSet set)
+ {
+ super(set);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count)
+ {
+ super(id, count);
+ _enchantLevel = 0;
+ }
+
+ public ItemEnchantHolder(int id, long count, int enchantLevel)
+ {
+ super(id, count);
+ _enchantLevel = enchantLevel;
+ }
+
+ /**
+ * @return enchant level of items contained in this object
+ */
+ public int getEnchantLevel()
+ {
+ return _enchantLevel;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ItemEnchantHolder objInstance))
+ {
+ return false;
+ }
+ else if (obj == this)
+ {
+ return true;
+ }
+ return (getId() == objInstance.getId()) && ((getCount() == objInstance.getCount()) && (_enchantLevel == objInstance.getEnchantLevel()));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", count: " + getCount() + ", enchant level: " + _enchantLevel;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
new file mode 100644
index 0000000000..18b52391a5
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/UniqueItemEnchantHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import org.l2jmobius.gameserver.model.interfaces.IUniqueId;
+
+/**
+ * @author Index, Mobius
+ */
+public class UniqueItemEnchantHolder extends ItemEnchantHolder implements IUniqueId
+{
+ private final int _objectId;
+
+ public UniqueItemEnchantHolder(int id, int objectId)
+ {
+ this(id, objectId, 1);
+ }
+
+ public UniqueItemEnchantHolder(int id, int objectId, long count)
+ {
+ super(id, count);
+ _objectId = objectId;
+ }
+
+ public UniqueItemEnchantHolder(ItemEnchantHolder itemHolder, int objectId)
+ {
+ super(itemHolder.getId(), itemHolder.getCount(), itemHolder.getEnchantLevel());
+ _objectId = objectId;
+ }
+
+ @Override
+ public int getObjectId()
+ {
+ return _objectId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + "] ID: " + getId() + ", object ID: " + _objectId + ", count: " + getCount() + ", enchant level: " + getEnchantLevel();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 9bdf7ad57c..16c9e16857 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -96,6 +96,7 @@ import org.l2jmobius.gameserver.network.clientpackets.enchant.single.ExRequestVi
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
+import org.l2jmobius.gameserver.network.clientpackets.equipmentupgradenormal.ExUpgradeSystemNormalRequest;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneEnter;
import org.l2jmobius.gameserver.network.clientpackets.huntingzones.ExTimedHuntingZoneList;
@@ -548,7 +549,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
EX_INTERACT_MODIFY(0x15F, null, ConnectionState.IN_GAME),
EX_TRY_ENCHANT_ARTIFACT(0x160, null, ConnectionState.IN_GAME),
- EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, null, ConnectionState.IN_GAME),
+ EX_UPGRADE_SYSTEM_NORMAL_REQUEST(0x161, ExUpgradeSystemNormalRequest::new, 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
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
new file mode 100644
index 0000000000..0a7115efe0
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/equipmentupgradenormal/ExUpgradeSystemNormalRequest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.enums.UpgradeDataType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.EquipmentUpgradeNormalHolder;
+import org.l2jmobius.gameserver.model.holders.ItemEnchantHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.model.item.instance.Item;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.PacketLogger;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.equipmentupgradenormal.ExUpgradeSystemNormalResult;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalRequest implements IClientIncomingPacket
+{
+ private int _objectId;
+ private int _typeId;
+ private int _upgradeId;
+
+ private final List _resultItems = new ArrayList<>();
+ private final List _bonusItems = new ArrayList<>();
+ private final Map _discount = new HashMap<>();
+ private boolean isNeedToSendUpdate = false;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _objectId = packet.readD();
+ _typeId = packet.readD();
+ _upgradeId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+ final Item requestedItem = player.getInventory().getItemByObjectId(_objectId);
+ if (requestedItem == null)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ final EquipmentUpgradeNormalHolder upgradeHolder = EquipmentUpgradeNormalData.getInstance().getUpgrade(_upgradeId);
+ if ((upgradeHolder == null) || (upgradeHolder.getType() != _typeId))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ final Inventory inventory = player.getInventory();
+ if ((inventory.getItemByItemId(upgradeHolder.getInitialItem().getId()) == null) || (inventory.getInventoryItemCount(upgradeHolder.getInitialItem().getId(), -1) < upgradeHolder.getInitialItem().getCount()))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemEnchantHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ if (material.getCount() < 0)
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ PacketLogger.warning(getClass().getSimpleName() + ": material -> item -> count in file EquipmentUpgradeNormalData.xml for upgrade id " + upgradeHolder.getId() + " cant be less than 0! Aborting current request!");
+ return;
+ }
+ if (inventory.getInventoryItemCount(material.getId(), material.getEnchantLevel()) < material.getCount())
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ for (ItemHolder discount : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ if (discount.getId() == material.getId())
+ {
+ _discount.put(material.getId(), discount.getCount());
+ break;
+ }
+ }
+ }
+ }
+ final long adena = upgradeHolder.getCommission();
+ if ((adena > 0) && (inventory.getAdena() < adena))
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ return;
+ }
+
+ // Get materials.
+ player.destroyItem("UpgradeNormalEquipment", _objectId, 1, player, true);
+ if (upgradeHolder.isHasCategory(UpgradeDataType.MATERIAL))
+ {
+ for (ItemHolder material : upgradeHolder.getItems(UpgradeDataType.MATERIAL))
+ {
+ player.destroyItemByItemId("UpgradeNormalEquipment", material.getId(), material.getCount() - (_discount.isEmpty() ? 0 : _discount.get(material.getId())), player, true);
+ }
+ }
+ if (adena > 0)
+ {
+ player.reduceAdena("UpgradeNormalEquipment", adena, player, true);
+ }
+
+ if (Rnd.get(100d) < upgradeHolder.getChance())
+ {
+ for (ItemEnchantHolder successItem : upgradeHolder.getItems(UpgradeDataType.ON_SUCCESS))
+ {
+ final Item addedSuccessItem = player.addItem("UpgradeNormalEquipment", successItem.getId(), successItem.getCount(), player, true);
+ if (successItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedSuccessItem.setEnchantLevel(successItem.getEnchantLevel());
+ }
+ addedSuccessItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(successItem, addedSuccessItem.getObjectId()));
+ }
+ if (upgradeHolder.isHasCategory(UpgradeDataType.BONUS_TYPE) && (Rnd.get(100d) < upgradeHolder.getChanceToReceiveBonusItems()))
+ {
+ for (ItemEnchantHolder bonusItem : upgradeHolder.getItems(UpgradeDataType.BONUS_TYPE))
+ {
+ final Item addedBonusItem = player.addItem("UpgradeNormalEquipment", bonusItem.getId(), bonusItem.getCount(), player, true);
+ if (bonusItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedBonusItem.setEnchantLevel(bonusItem.getEnchantLevel());
+ }
+ addedBonusItem.updateDatabase(true);
+ _bonusItems.add(new UniqueItemEnchantHolder(bonusItem, addedBonusItem.getObjectId()));
+ }
+ }
+ }
+ else
+ {
+ if (upgradeHolder.isHasCategory(UpgradeDataType.ON_FAILURE))
+ {
+ for (ItemEnchantHolder failureItem : upgradeHolder.getItems(UpgradeDataType.ON_FAILURE))
+ {
+ final Item addedFailureItem = player.addItem("UpgradeNormalEquipment", failureItem.getId(), failureItem.getCount(), player, true);
+ if (failureItem.getEnchantLevel() != 0)
+ {
+ isNeedToSendUpdate = true;
+ addedFailureItem.setEnchantLevel(failureItem.getEnchantLevel());
+ }
+ addedFailureItem.updateDatabase(true);
+ _resultItems.add(new UniqueItemEnchantHolder(failureItem, addedFailureItem.getObjectId()));
+ }
+ }
+ else
+ {
+ player.sendPacket(ExUpgradeSystemNormalResult.FAIL);
+ }
+ }
+ if (isNeedToSendUpdate)
+ {
+ player.sendItemList(); // for see enchant level in Upgrade UI
+ }
+ // Why need map of item and count? because method "addItem" return item, and if it exists in result will be count of all items, not of obtained.
+ player.sendPacket(new ExUpgradeSystemNormalResult(1, _typeId, true, _resultItems, _bonusItems));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
new file mode 100644
index 0000000000..ff55a2ed25
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExShowUpgradeSystemNormal.java
@@ -0,0 +1,70 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.EquipmentUpgradeNormalData;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExShowUpgradeSystemNormal extends AbstractItemPacket
+{
+ private final int _mode;
+ private final int _type;
+ private final int _commission;
+ private final List _materials = new ArrayList<>();
+ private final List _discountRatio = new ArrayList<>();
+
+ public ExShowUpgradeSystemNormal(int mode, int type)
+ {
+ _mode = mode;
+ _type = type;
+ _commission = EquipmentUpgradeNormalData.getInstance().getCommission();
+ for (ItemHolder item : EquipmentUpgradeNormalData.getInstance().getDiscount())
+ {
+ _materials.add(item.getId());
+ _discountRatio.add((int) item.getCount());
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_SHOW_UPGRADE_SYSTEM_NORMAL.writeId(packet);
+ packet.writeH(_mode);
+ packet.writeH(_type);
+ packet.writeH(_commission); // default - 100
+ packet.writeD(_materials.size()); // array of materials with discount
+ for (int id : _materials)
+ {
+ packet.writeD(id);
+ }
+ packet.writeD(_discountRatio.size()); // array of discount count
+ for (int discount : _discountRatio)
+ {
+ packet.writeD(discount);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
new file mode 100644
index 0000000000..1409425294
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/equipmentupgradenormal/ExUpgradeSystemNormalResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.equipmentupgradenormal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.holders.UniqueItemEnchantHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Index
+ */
+public class ExUpgradeSystemNormalResult extends AbstractItemPacket
+{
+ public static final ExUpgradeSystemNormalResult FAIL = new ExUpgradeSystemNormalResult(0, 0, false, Collections.emptyList(), Collections.emptyList());
+
+ private final int _result;
+ private final int _upgradeId;
+ private final boolean _success;
+ private final List _resultItems;
+ private final List _bonusItems;
+
+ public ExUpgradeSystemNormalResult(int result, int upgradeId, boolean success, List resultItems, List bonusItems)
+ {
+ _result = result;
+ _upgradeId = upgradeId;
+ _success = success;
+ _resultItems = resultItems;
+ _bonusItems = bonusItems;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_UPGRADE_SYSTEM_NORMAL_RESULT.writeId(packet);
+ packet.writeH(_result); // Result ID
+ packet.writeD(_upgradeId); // Upgrade ID
+ packet.writeC(_success ? 1 : 0); // Success
+ packet.writeD(_resultItems.size()); // Array of result items (success/failure) start.
+ for (UniqueItemEnchantHolder item : _resultItems)
+ {
+ packet.writeD(item.getObjectId());
+ packet.writeD(item.getId());
+ packet.writeD(item.getEnchantLevel());
+ packet.writeD(Math.toIntExact(item.getCount()));
+ }
+ packet.writeC(0); // Is bonus? Do not see any effect.
+ packet.writeD(_bonusItems.size()); // Array of bonus items start.
+ for (UniqueItemEnchantHolder bonus : _bonusItems)
+ {
+ packet.writeD(bonus.getObjectId());
+ packet.writeD(bonus.getId());
+ packet.writeD(bonus.getEnchantLevel());
+ packet.writeD(Math.toIntExact(bonus.getCount()));
+ }
+ return true;
+ }
+}