diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/MasterHandler.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/MasterHandler.java
index b5ff946dc4..b7d7db0504 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/MasterHandler.java
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/MasterHandler.java
@@ -185,6 +185,7 @@ import handlers.itemhandlers.BlessedSpiritShot;
import handlers.itemhandlers.Book;
import handlers.itemhandlers.Bypass;
import handlers.itemhandlers.Calculator;
+import handlers.itemhandlers.ChangeAttributeCrystal;
import handlers.itemhandlers.CharmOfCourage;
import handlers.itemhandlers.Elixir;
import handlers.itemhandlers.EnchantAttribute;
@@ -523,6 +524,7 @@ public class MasterHandler
Book.class,
Bypass.class,
Calculator.class,
+ ChangeAttributeCrystal.class,
CharmOfCourage.class,
Elixir.class,
EnchantAttribute.class,
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
new file mode 100644
index 0000000000..d31ba1bb2b
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
@@ -0,0 +1,86 @@
+/*
+ * 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 handlers.itemhandlers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.l2jmobius.gameserver.enums.ItemGrade;
+import com.l2jmobius.gameserver.enums.PrivateStoreType;
+import com.l2jmobius.gameserver.handler.IItemHandler;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.model.actor.L2Playable;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeItemList;
+
+/**
+ * @author Mobius
+ */
+public class ChangeAttributeCrystal implements IItemHandler
+{
+ private static final Map ITEM_GRADES = new HashMap<>();
+ {
+ ITEM_GRADES.put(33502, ItemGrade.S);
+ ITEM_GRADES.put(35749, ItemGrade.R);
+ }
+
+ @Override
+ public boolean useItem(L2Playable playable, L2ItemInstance item, boolean forceUse)
+ {
+ if (!playable.isPlayer())
+ {
+ playable.sendPacket(SystemMessageId.YOUR_PET_CANNOT_CARRY_THIS_ITEM);
+ return false;
+ }
+
+ final L2PcInstance player = playable.getActingPlayer();
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CANNOT_CHANGE_AN_ATTRIBUTE_WHILE_USING_A_PRIVATE_STORE_OR_WORKSHOP));
+ return false;
+ }
+
+ if (ITEM_GRADES.get(item.getId()) == null)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CHANGING_ATTRIBUTES_HAS_BEEN_FAILED));
+ return false;
+ }
+
+ final List itemList = new ArrayList<>();
+ for (L2ItemInstance i : player.getInventory().getItems())
+ {
+ if (i.isWeapon() && i.hasAttributes() && (i.getItem().getItemGrade() == ITEM_GRADES.get(item.getId())))
+ {
+ itemList.add(new ItemInfo(i));
+ }
+ }
+
+ if (itemList.isEmpty())
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_ITEM_FOR_CHANGING_AN_ATTRIBUTE_DOES_NOT_EXIST));
+ return false;
+ }
+
+ player.sendPacket(new ExChangeAttributeItemList(item.getId(), itemList.toArray(new ItemInfo[itemList.size()])));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/33500-33599.xml b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/33500-33599.xml
index 3ce58121e1..8b58995a22 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/33500-33599.xml
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/33500-33599.xml
@@ -42,14 +42,10 @@
-
-
+
-
-
-
-
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/35700-35799.xml b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/35700-35799.xml
index 4e12723bba..1be7452ede 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/35700-35799.xml
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/items/35700-35799.xml
@@ -942,14 +942,10 @@
-
-
+
-
-
-
-
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
index cc274bcf8e..a3e8d10735 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -40,6 +40,9 @@ import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExCancel
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingEnchantSupportItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestShapeShiftingItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeCancel;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.SendChangeAttributeTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.awakening.RequestCallToChangeClass;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCancelCuriousHouse;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
@@ -256,9 +259,9 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_FIRST_PLAY_START(0xAC, null, ConnectionState.IN_GAME),
REQUEST_FLY_MOVE_START(0xAD, RequestFlyMoveStart::new, ConnectionState.IN_GAME),
REQUEST_HARDWARE_INFO(0xAE, RequestHardWareInfo::new, ConnectionState.values()),
- SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, null, ConnectionState.IN_GAME),
+ SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, SendChangeAttributeTargetItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, RequestChangeAttributeItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, RequestChangeAttributeCancel::new, ConnectionState.IN_GAME),
REQUEST_BR_PRESENT_BUY_PRODUCT(0xB3, null, ConnectionState.IN_GAME),
CONFIRM_MENTEE_ADD(0xB4, ConfirmMenteeAdd::new, ConnectionState.IN_GAME),
REQUEST_MENTOR_CANCEL(0xB5, RequestMentorCancel::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
new file mode 100644
index 0000000000..8f006158f6
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
@@ -0,0 +1,46 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeCancel implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+ activeChar.sendPacket(ExChangeAttributeFail.STATIC);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
new file mode 100644
index 0000000000..a27dbe1558
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
@@ -0,0 +1,92 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
+import com.l2jmobius.gameserver.model.items.enchant.attribute.AttributeHolder;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeOk;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeItem implements IClientIncomingPacket
+{
+ private int _consumeItemId;
+ private int _itemObjId;
+ private int _newElementId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _consumeItemId = packet.readD();
+ _itemObjId = packet.readD();
+ _newElementId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final PcInventory inventory = activeChar.getInventory();
+ final L2ItemInstance item = inventory.getItemByObjectId(_itemObjId);
+
+ // attempting to destroy item
+ if (activeChar.getInventory().destroyItemByItemId("ChangeAttribute", _consumeItemId, 1, activeChar, item) == null)
+ {
+ client.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT2);
+ client.sendPacket(ExChangeAttributeFail.STATIC);
+ Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " tried to change attribute without an attribute change crystal.", Config.DEFAULT_PUNISH);
+ return;
+ }
+
+ // get values
+ final int oldElementId = item.getAttackAttributeType().getClientId();
+ final int elementValue = item.getAttackAttribute().getValue();
+ item.clearAllAttributes();
+ item.setAttribute(new AttributeHolder(AttributeType.findByClientId(_newElementId), elementValue));
+
+ // send packets
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S1_S_S2_ATTRIBUTE_HAS_SUCCESSFULLY_CHANGED_TO_S3_ATTRIBUTE);
+ msg.addItemName(item);
+ msg.addAttribute(oldElementId);
+ msg.addAttribute(_newElementId);
+ activeChar.sendPacket(msg);
+ InventoryUpdate iu = new InventoryUpdate();
+ iu.addModifiedItem(item);
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ activeChar.sendPacket(ExChangeAttributeOk.STATIC);
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
new file mode 100644
index 0000000000..5aca074929
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeInfo;
+
+/**
+ * @author Mobius
+ */
+public class SendChangeAttributeTargetItem implements IClientIncomingPacket
+{
+ private int _crystalItemId;
+ private int _itemObjId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _crystalItemId = packet.readD();
+ _itemObjId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(_itemObjId);
+ if ((item == null) || !item.isWeapon())
+ {
+ activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+ return;
+ }
+
+ activeChar.sendPacket(new ExChangeAttributeInfo(_crystalItemId, item));
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
new file mode 100644
index 0000000000..81a40c1546
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeFail implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeFail();
+
+ public ExChangeAttributeFail()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_FAIL.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
new file mode 100644
index 0000000000..efd669df25
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeInfo implements IClientOutgoingPacket
+{
+ private static final Map ATTRIBUTE_MASKS = new HashMap<>();
+ {
+ ATTRIBUTE_MASKS.put(AttributeType.FIRE, (byte) 1);
+ ATTRIBUTE_MASKS.put(AttributeType.WATER, (byte) 2);
+ ATTRIBUTE_MASKS.put(AttributeType.WIND, (byte) 4);
+ ATTRIBUTE_MASKS.put(AttributeType.EARTH, (byte) 8);
+ ATTRIBUTE_MASKS.put(AttributeType.HOLY, (byte) 16);
+ ATTRIBUTE_MASKS.put(AttributeType.DARK, (byte) 32);
+ }
+
+ private final int _crystalItemId;
+ private int _attributes;
+ private int _itemObjId;
+
+ public ExChangeAttributeInfo(int crystalItemId, L2ItemInstance item)
+ {
+ _crystalItemId = crystalItemId;
+ _attributes = 0;
+ for (AttributeType e : AttributeType.ATTRIBUTE_TYPES)
+ {
+ if (e != item.getAttackAttributeType())
+ {
+ _attributes |= ATTRIBUTE_MASKS.get(e);
+ }
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_INFO.writeId(packet);
+ packet.writeD(_crystalItemId);
+ packet.writeD(_attributes);
+ packet.writeD(_itemObjId);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
new file mode 100644
index 0000000000..4b266e2e33
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeItemList extends AbstractItemPacket
+{
+ private final ItemInfo[] _itemsList;
+ private final int _itemId;
+
+ public ExChangeAttributeItemList(int itemId, ItemInfo[] itemsList)
+ {
+ _itemId = itemId;
+ _itemsList = itemsList;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_ITEM_LIST.writeId(packet);
+ packet.writeD(_itemId);
+ packet.writeD(_itemsList.length);
+ for (ItemInfo item : _itemsList)
+ {
+ writeItem(packet, item);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
new file mode 100644
index 0000000000..5efc5e80e4
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeOk implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeOk();
+
+ public ExChangeAttributeOk()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_OK.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/MasterHandler.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/MasterHandler.java
index e172ebdbf7..0597274dfa 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/MasterHandler.java
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/MasterHandler.java
@@ -186,6 +186,7 @@ import handlers.itemhandlers.BlessedSpiritShot;
import handlers.itemhandlers.Book;
import handlers.itemhandlers.Bypass;
import handlers.itemhandlers.Calculator;
+import handlers.itemhandlers.ChangeAttributeCrystal;
import handlers.itemhandlers.CharmOfCourage;
import handlers.itemhandlers.Elixir;
import handlers.itemhandlers.EnchantAttribute;
@@ -525,6 +526,7 @@ public class MasterHandler
Book.class,
Bypass.class,
Calculator.class,
+ ChangeAttributeCrystal.class,
CharmOfCourage.class,
Elixir.class,
EnchantAttribute.class,
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
new file mode 100644
index 0000000000..8d4c67b05f
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
@@ -0,0 +1,87 @@
+/*
+ * 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 handlers.itemhandlers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.l2jmobius.gameserver.enums.ItemGrade;
+import com.l2jmobius.gameserver.enums.PrivateStoreType;
+import com.l2jmobius.gameserver.handler.IItemHandler;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.model.actor.L2Playable;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeItemList;
+
+/**
+ * @author Mobius
+ */
+public class ChangeAttributeCrystal implements IItemHandler
+{
+ private static final Map ITEM_GRADES = new HashMap<>();
+ {
+ ITEM_GRADES.put(33502, ItemGrade.S);
+ ITEM_GRADES.put(35749, ItemGrade.R);
+ ITEM_GRADES.put(45817, ItemGrade.R);
+ }
+
+ @Override
+ public boolean useItem(L2Playable playable, L2ItemInstance item, boolean forceUse)
+ {
+ if (!playable.isPlayer())
+ {
+ playable.sendPacket(SystemMessageId.YOUR_PET_CANNOT_CARRY_THIS_ITEM);
+ return false;
+ }
+
+ final L2PcInstance player = playable.getActingPlayer();
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CANNOT_CHANGE_AN_ATTRIBUTE_WHILE_USING_A_PRIVATE_STORE_OR_WORKSHOP));
+ return false;
+ }
+
+ if (ITEM_GRADES.get(item.getId()) == null)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CHANGING_ATTRIBUTES_HAS_BEEN_FAILED));
+ return false;
+ }
+
+ final List itemList = new ArrayList<>();
+ for (L2ItemInstance i : player.getInventory().getItems())
+ {
+ if (i.isWeapon() && i.hasAttributes() && (i.getItem().getItemGrade() == ITEM_GRADES.get(item.getId())))
+ {
+ itemList.add(new ItemInfo(i));
+ }
+ }
+
+ if (itemList.isEmpty())
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_ITEM_FOR_CHANGING_AN_ATTRIBUTE_DOES_NOT_EXIST));
+ return false;
+ }
+
+ player.sendPacket(new ExChangeAttributeItemList(item.getId(), itemList.toArray(new ItemInfo[itemList.size()])));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/33500-33599.xml b/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/33500-33599.xml
index 0c0b0ffea9..ec5ac8db2a 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/33500-33599.xml
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/33500-33599.xml
@@ -42,14 +42,10 @@
-
-
+
-
-
-
-
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/35700-35799.xml b/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/35700-35799.xml
index 69d379e867..b6175fa981 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/35700-35799.xml
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/35700-35799.xml
@@ -942,14 +942,10 @@
-
-
+
-
-
-
-
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/45800-45899.xml b/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/45800-45899.xml
index 636fae7c6f..916543ba8d 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/45800-45899.xml
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/stats/items/45800-45899.xml
@@ -354,10 +354,14 @@
-
+
+
-
+
+
+
-
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
index c7b610ed0c..e68607b997 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -40,6 +40,9 @@ import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExCancel
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingEnchantSupportItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestShapeShiftingItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeCancel;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.SendChangeAttributeTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.awakening.RequestCallToChangeClass;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCancelCuriousHouse;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
@@ -262,9 +265,9 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_FIRST_PLAY_START(0xAC, null, ConnectionState.IN_GAME),
REQUEST_FLY_MOVE_START(0xAD, RequestFlyMoveStart::new, ConnectionState.IN_GAME),
REQUEST_HARDWARE_INFO(0xAE, RequestHardWareInfo::new, ConnectionState.values()),
- SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, null, ConnectionState.IN_GAME),
+ SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, SendChangeAttributeTargetItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, RequestChangeAttributeItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, RequestChangeAttributeCancel::new, ConnectionState.IN_GAME),
REQUEST_BR_PRESENT_BUY_PRODUCT(0xB3, null, ConnectionState.IN_GAME),
CONFIRM_MENTEE_ADD(0xB4, ConfirmMenteeAdd::new, ConnectionState.IN_GAME),
REQUEST_MENTOR_CANCEL(0xB5, RequestMentorCancel::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
new file mode 100644
index 0000000000..8f006158f6
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
@@ -0,0 +1,46 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeCancel implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+ activeChar.sendPacket(ExChangeAttributeFail.STATIC);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
new file mode 100644
index 0000000000..a27dbe1558
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
@@ -0,0 +1,92 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
+import com.l2jmobius.gameserver.model.items.enchant.attribute.AttributeHolder;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeOk;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeItem implements IClientIncomingPacket
+{
+ private int _consumeItemId;
+ private int _itemObjId;
+ private int _newElementId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _consumeItemId = packet.readD();
+ _itemObjId = packet.readD();
+ _newElementId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final PcInventory inventory = activeChar.getInventory();
+ final L2ItemInstance item = inventory.getItemByObjectId(_itemObjId);
+
+ // attempting to destroy item
+ if (activeChar.getInventory().destroyItemByItemId("ChangeAttribute", _consumeItemId, 1, activeChar, item) == null)
+ {
+ client.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT2);
+ client.sendPacket(ExChangeAttributeFail.STATIC);
+ Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " tried to change attribute without an attribute change crystal.", Config.DEFAULT_PUNISH);
+ return;
+ }
+
+ // get values
+ final int oldElementId = item.getAttackAttributeType().getClientId();
+ final int elementValue = item.getAttackAttribute().getValue();
+ item.clearAllAttributes();
+ item.setAttribute(new AttributeHolder(AttributeType.findByClientId(_newElementId), elementValue));
+
+ // send packets
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S1_S_S2_ATTRIBUTE_HAS_SUCCESSFULLY_CHANGED_TO_S3_ATTRIBUTE);
+ msg.addItemName(item);
+ msg.addAttribute(oldElementId);
+ msg.addAttribute(_newElementId);
+ activeChar.sendPacket(msg);
+ InventoryUpdate iu = new InventoryUpdate();
+ iu.addModifiedItem(item);
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ activeChar.sendPacket(ExChangeAttributeOk.STATIC);
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
new file mode 100644
index 0000000000..5aca074929
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeInfo;
+
+/**
+ * @author Mobius
+ */
+public class SendChangeAttributeTargetItem implements IClientIncomingPacket
+{
+ private int _crystalItemId;
+ private int _itemObjId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _crystalItemId = packet.readD();
+ _itemObjId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(_itemObjId);
+ if ((item == null) || !item.isWeapon())
+ {
+ activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+ return;
+ }
+
+ activeChar.sendPacket(new ExChangeAttributeInfo(_crystalItemId, item));
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
new file mode 100644
index 0000000000..81a40c1546
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeFail implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeFail();
+
+ public ExChangeAttributeFail()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_FAIL.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
new file mode 100644
index 0000000000..efd669df25
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeInfo implements IClientOutgoingPacket
+{
+ private static final Map ATTRIBUTE_MASKS = new HashMap<>();
+ {
+ ATTRIBUTE_MASKS.put(AttributeType.FIRE, (byte) 1);
+ ATTRIBUTE_MASKS.put(AttributeType.WATER, (byte) 2);
+ ATTRIBUTE_MASKS.put(AttributeType.WIND, (byte) 4);
+ ATTRIBUTE_MASKS.put(AttributeType.EARTH, (byte) 8);
+ ATTRIBUTE_MASKS.put(AttributeType.HOLY, (byte) 16);
+ ATTRIBUTE_MASKS.put(AttributeType.DARK, (byte) 32);
+ }
+
+ private final int _crystalItemId;
+ private int _attributes;
+ private int _itemObjId;
+
+ public ExChangeAttributeInfo(int crystalItemId, L2ItemInstance item)
+ {
+ _crystalItemId = crystalItemId;
+ _attributes = 0;
+ for (AttributeType e : AttributeType.ATTRIBUTE_TYPES)
+ {
+ if (e != item.getAttackAttributeType())
+ {
+ _attributes |= ATTRIBUTE_MASKS.get(e);
+ }
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_INFO.writeId(packet);
+ packet.writeD(_crystalItemId);
+ packet.writeD(_attributes);
+ packet.writeD(_itemObjId);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
new file mode 100644
index 0000000000..4b266e2e33
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeItemList extends AbstractItemPacket
+{
+ private final ItemInfo[] _itemsList;
+ private final int _itemId;
+
+ public ExChangeAttributeItemList(int itemId, ItemInfo[] itemsList)
+ {
+ _itemId = itemId;
+ _itemsList = itemsList;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_ITEM_LIST.writeId(packet);
+ packet.writeD(_itemId);
+ packet.writeD(_itemsList.length);
+ for (ItemInfo item : _itemsList)
+ {
+ writeItem(packet, item);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
new file mode 100644
index 0000000000..5efc5e80e4
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeOk implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeOk();
+
+ public ExChangeAttributeOk()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_OK.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/MasterHandler.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/MasterHandler.java
index 4e5398f278..660f6f01c8 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/MasterHandler.java
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/MasterHandler.java
@@ -186,6 +186,7 @@ import handlers.itemhandlers.BlessedSpiritShot;
import handlers.itemhandlers.Book;
import handlers.itemhandlers.Bypass;
import handlers.itemhandlers.Calculator;
+import handlers.itemhandlers.ChangeAttributeCrystal;
import handlers.itemhandlers.CharmOfCourage;
import handlers.itemhandlers.Elixir;
import handlers.itemhandlers.EnchantAttribute;
@@ -526,6 +527,7 @@ public class MasterHandler
Book.class,
Bypass.class,
Calculator.class,
+ ChangeAttributeCrystal.class,
CharmOfCourage.class,
Elixir.class,
EnchantAttribute.class,
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
new file mode 100644
index 0000000000..8d4c67b05f
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
@@ -0,0 +1,87 @@
+/*
+ * 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 handlers.itemhandlers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.l2jmobius.gameserver.enums.ItemGrade;
+import com.l2jmobius.gameserver.enums.PrivateStoreType;
+import com.l2jmobius.gameserver.handler.IItemHandler;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.model.actor.L2Playable;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeItemList;
+
+/**
+ * @author Mobius
+ */
+public class ChangeAttributeCrystal implements IItemHandler
+{
+ private static final Map ITEM_GRADES = new HashMap<>();
+ {
+ ITEM_GRADES.put(33502, ItemGrade.S);
+ ITEM_GRADES.put(35749, ItemGrade.R);
+ ITEM_GRADES.put(45817, ItemGrade.R);
+ }
+
+ @Override
+ public boolean useItem(L2Playable playable, L2ItemInstance item, boolean forceUse)
+ {
+ if (!playable.isPlayer())
+ {
+ playable.sendPacket(SystemMessageId.YOUR_PET_CANNOT_CARRY_THIS_ITEM);
+ return false;
+ }
+
+ final L2PcInstance player = playable.getActingPlayer();
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CANNOT_CHANGE_AN_ATTRIBUTE_WHILE_USING_A_PRIVATE_STORE_OR_WORKSHOP));
+ return false;
+ }
+
+ if (ITEM_GRADES.get(item.getId()) == null)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CHANGING_ATTRIBUTES_HAS_BEEN_FAILED));
+ return false;
+ }
+
+ final List itemList = new ArrayList<>();
+ for (L2ItemInstance i : player.getInventory().getItems())
+ {
+ if (i.isWeapon() && i.hasAttributes() && (i.getItem().getItemGrade() == ITEM_GRADES.get(item.getId())))
+ {
+ itemList.add(new ItemInfo(i));
+ }
+ }
+
+ if (itemList.isEmpty())
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_ITEM_FOR_CHANGING_AN_ATTRIBUTE_DOES_NOT_EXIST));
+ return false;
+ }
+
+ player.sendPacket(new ExChangeAttributeItemList(item.getId(), itemList.toArray(new ItemInfo[itemList.size()])));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/33500-33599.xml b/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/33500-33599.xml
index 70db639416..8c7023c09a 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/33500-33599.xml
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/33500-33599.xml
@@ -42,14 +42,10 @@
-
-
+
-
-
-
-
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/35700-35799.xml b/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/35700-35799.xml
index 7d46a60fe6..40cd9dbe68 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/35700-35799.xml
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/35700-35799.xml
@@ -942,14 +942,10 @@
-
-
+
-
-
-
-
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/45800-45899.xml b/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/45800-45899.xml
index 04fecad368..9bbf208918 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/45800-45899.xml
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/stats/items/45800-45899.xml
@@ -354,10 +354,14 @@
-
+
+
-
+
+
+
-
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
index 5f71b629d9..c00a32ad43 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -40,6 +40,9 @@ import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExCancel
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingEnchantSupportItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestShapeShiftingItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeCancel;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.SendChangeAttributeTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.awakening.RequestCallToChangeClass;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCancelCuriousHouse;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
@@ -263,9 +266,9 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_FIRST_PLAY_START(0xAC, null, ConnectionState.IN_GAME),
REQUEST_FLY_MOVE_START(0xAD, RequestFlyMoveStart::new, ConnectionState.IN_GAME),
REQUEST_HARDWARE_INFO(0xAE, RequestHardWareInfo::new, ConnectionState.values()),
- SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, null, ConnectionState.IN_GAME),
+ SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, SendChangeAttributeTargetItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, RequestChangeAttributeItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, RequestChangeAttributeCancel::new, ConnectionState.IN_GAME),
REQUEST_BR_PRESENT_BUY_PRODUCT(0xB3, null, ConnectionState.IN_GAME),
CONFIRM_MENTEE_ADD(0xB4, ConfirmMenteeAdd::new, ConnectionState.IN_GAME),
REQUEST_MENTOR_CANCEL(0xB5, RequestMentorCancel::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
new file mode 100644
index 0000000000..8f006158f6
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
@@ -0,0 +1,46 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeCancel implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+ activeChar.sendPacket(ExChangeAttributeFail.STATIC);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
new file mode 100644
index 0000000000..a27dbe1558
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
@@ -0,0 +1,92 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
+import com.l2jmobius.gameserver.model.items.enchant.attribute.AttributeHolder;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeOk;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeItem implements IClientIncomingPacket
+{
+ private int _consumeItemId;
+ private int _itemObjId;
+ private int _newElementId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _consumeItemId = packet.readD();
+ _itemObjId = packet.readD();
+ _newElementId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final PcInventory inventory = activeChar.getInventory();
+ final L2ItemInstance item = inventory.getItemByObjectId(_itemObjId);
+
+ // attempting to destroy item
+ if (activeChar.getInventory().destroyItemByItemId("ChangeAttribute", _consumeItemId, 1, activeChar, item) == null)
+ {
+ client.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT2);
+ client.sendPacket(ExChangeAttributeFail.STATIC);
+ Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " tried to change attribute without an attribute change crystal.", Config.DEFAULT_PUNISH);
+ return;
+ }
+
+ // get values
+ final int oldElementId = item.getAttackAttributeType().getClientId();
+ final int elementValue = item.getAttackAttribute().getValue();
+ item.clearAllAttributes();
+ item.setAttribute(new AttributeHolder(AttributeType.findByClientId(_newElementId), elementValue));
+
+ // send packets
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S1_S_S2_ATTRIBUTE_HAS_SUCCESSFULLY_CHANGED_TO_S3_ATTRIBUTE);
+ msg.addItemName(item);
+ msg.addAttribute(oldElementId);
+ msg.addAttribute(_newElementId);
+ activeChar.sendPacket(msg);
+ InventoryUpdate iu = new InventoryUpdate();
+ iu.addModifiedItem(item);
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ activeChar.sendPacket(ExChangeAttributeOk.STATIC);
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
new file mode 100644
index 0000000000..5aca074929
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeInfo;
+
+/**
+ * @author Mobius
+ */
+public class SendChangeAttributeTargetItem implements IClientIncomingPacket
+{
+ private int _crystalItemId;
+ private int _itemObjId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _crystalItemId = packet.readD();
+ _itemObjId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(_itemObjId);
+ if ((item == null) || !item.isWeapon())
+ {
+ activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+ return;
+ }
+
+ activeChar.sendPacket(new ExChangeAttributeInfo(_crystalItemId, item));
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
new file mode 100644
index 0000000000..81a40c1546
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeFail implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeFail();
+
+ public ExChangeAttributeFail()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_FAIL.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
new file mode 100644
index 0000000000..efd669df25
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeInfo implements IClientOutgoingPacket
+{
+ private static final Map ATTRIBUTE_MASKS = new HashMap<>();
+ {
+ ATTRIBUTE_MASKS.put(AttributeType.FIRE, (byte) 1);
+ ATTRIBUTE_MASKS.put(AttributeType.WATER, (byte) 2);
+ ATTRIBUTE_MASKS.put(AttributeType.WIND, (byte) 4);
+ ATTRIBUTE_MASKS.put(AttributeType.EARTH, (byte) 8);
+ ATTRIBUTE_MASKS.put(AttributeType.HOLY, (byte) 16);
+ ATTRIBUTE_MASKS.put(AttributeType.DARK, (byte) 32);
+ }
+
+ private final int _crystalItemId;
+ private int _attributes;
+ private int _itemObjId;
+
+ public ExChangeAttributeInfo(int crystalItemId, L2ItemInstance item)
+ {
+ _crystalItemId = crystalItemId;
+ _attributes = 0;
+ for (AttributeType e : AttributeType.ATTRIBUTE_TYPES)
+ {
+ if (e != item.getAttackAttributeType())
+ {
+ _attributes |= ATTRIBUTE_MASKS.get(e);
+ }
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_INFO.writeId(packet);
+ packet.writeD(_crystalItemId);
+ packet.writeD(_attributes);
+ packet.writeD(_itemObjId);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
new file mode 100644
index 0000000000..4b266e2e33
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeItemList extends AbstractItemPacket
+{
+ private final ItemInfo[] _itemsList;
+ private final int _itemId;
+
+ public ExChangeAttributeItemList(int itemId, ItemInfo[] itemsList)
+ {
+ _itemId = itemId;
+ _itemsList = itemsList;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_ITEM_LIST.writeId(packet);
+ packet.writeD(_itemId);
+ packet.writeD(_itemsList.length);
+ for (ItemInfo item : _itemsList)
+ {
+ writeItem(packet, item);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
new file mode 100644
index 0000000000..5efc5e80e4
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeOk implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeOk();
+
+ public ExChangeAttributeOk()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_OK.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/MasterHandler.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/MasterHandler.java
index 36f9c9e070..7b9e6e9a3f 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/MasterHandler.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/MasterHandler.java
@@ -187,6 +187,7 @@ import handlers.itemhandlers.BlessedSpiritShot;
import handlers.itemhandlers.Book;
import handlers.itemhandlers.Bypass;
import handlers.itemhandlers.Calculator;
+import handlers.itemhandlers.ChangeAttributeCrystal;
import handlers.itemhandlers.CharmOfCourage;
import handlers.itemhandlers.Elixir;
import handlers.itemhandlers.EnchantAttribute;
@@ -527,6 +528,7 @@ public class MasterHandler
Book.class,
Bypass.class,
Calculator.class,
+ ChangeAttributeCrystal.class,
CharmOfCourage.class,
Elixir.class,
EnchantAttribute.class,
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
new file mode 100644
index 0000000000..8d4c67b05f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/itemhandlers/ChangeAttributeCrystal.java
@@ -0,0 +1,87 @@
+/*
+ * 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 handlers.itemhandlers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.l2jmobius.gameserver.enums.ItemGrade;
+import com.l2jmobius.gameserver.enums.PrivateStoreType;
+import com.l2jmobius.gameserver.handler.IItemHandler;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.model.actor.L2Playable;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeItemList;
+
+/**
+ * @author Mobius
+ */
+public class ChangeAttributeCrystal implements IItemHandler
+{
+ private static final Map ITEM_GRADES = new HashMap<>();
+ {
+ ITEM_GRADES.put(33502, ItemGrade.S);
+ ITEM_GRADES.put(35749, ItemGrade.R);
+ ITEM_GRADES.put(45817, ItemGrade.R);
+ }
+
+ @Override
+ public boolean useItem(L2Playable playable, L2ItemInstance item, boolean forceUse)
+ {
+ if (!playable.isPlayer())
+ {
+ playable.sendPacket(SystemMessageId.YOUR_PET_CANNOT_CARRY_THIS_ITEM);
+ return false;
+ }
+
+ final L2PcInstance player = playable.getActingPlayer();
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CANNOT_CHANGE_AN_ATTRIBUTE_WHILE_USING_A_PRIVATE_STORE_OR_WORKSHOP));
+ return false;
+ }
+
+ if (ITEM_GRADES.get(item.getId()) == null)
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CHANGING_ATTRIBUTES_HAS_BEEN_FAILED));
+ return false;
+ }
+
+ final List itemList = new ArrayList<>();
+ for (L2ItemInstance i : player.getInventory().getItems())
+ {
+ if (i.isWeapon() && i.hasAttributes() && (i.getItem().getItemGrade() == ITEM_GRADES.get(item.getId())))
+ {
+ itemList.add(new ItemInfo(i));
+ }
+ }
+
+ if (itemList.isEmpty())
+ {
+ player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_ITEM_FOR_CHANGING_AN_ATTRIBUTE_DOES_NOT_EXIST));
+ return false;
+ }
+
+ player.sendPacket(new ExChangeAttributeItemList(item.getId(), itemList.toArray(new ItemInfo[itemList.size()])));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
index 5f71b629d9..c00a32ad43 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -40,6 +40,9 @@ import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExCancel
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingEnchantSupportItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestExTryToPutShapeShiftingTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.appearance.RequestShapeShiftingItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeCancel;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.RequestChangeAttributeItem;
+import com.l2jmobius.gameserver.network.clientpackets.attributechange.SendChangeAttributeTargetItem;
import com.l2jmobius.gameserver.network.clientpackets.awakening.RequestCallToChangeClass;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCancelCuriousHouse;
import com.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
@@ -263,9 +266,9 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_FIRST_PLAY_START(0xAC, null, ConnectionState.IN_GAME),
REQUEST_FLY_MOVE_START(0xAD, RequestFlyMoveStart::new, ConnectionState.IN_GAME),
REQUEST_HARDWARE_INFO(0xAE, RequestHardWareInfo::new, ConnectionState.values()),
- SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, null, ConnectionState.IN_GAME),
- REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, null, ConnectionState.IN_GAME),
+ SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, SendChangeAttributeTargetItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, RequestChangeAttributeItem::new, ConnectionState.IN_GAME),
+ REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, RequestChangeAttributeCancel::new, ConnectionState.IN_GAME),
REQUEST_BR_PRESENT_BUY_PRODUCT(0xB3, null, ConnectionState.IN_GAME),
CONFIRM_MENTEE_ADD(0xB4, ConfirmMenteeAdd::new, ConnectionState.IN_GAME),
REQUEST_MENTOR_CANCEL(0xB5, RequestMentorCancel::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
new file mode 100644
index 0000000000..8f006158f6
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeCancel.java
@@ -0,0 +1,46 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeCancel implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+ activeChar.sendPacket(ExChangeAttributeFail.STATIC);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
new file mode 100644
index 0000000000..a27dbe1558
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/RequestChangeAttributeItem.java
@@ -0,0 +1,92 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
+import com.l2jmobius.gameserver.model.items.enchant.attribute.AttributeHolder;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeFail;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeOk;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author Mobius
+ */
+public class RequestChangeAttributeItem implements IClientIncomingPacket
+{
+ private int _consumeItemId;
+ private int _itemObjId;
+ private int _newElementId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _consumeItemId = packet.readD();
+ _itemObjId = packet.readD();
+ _newElementId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final PcInventory inventory = activeChar.getInventory();
+ final L2ItemInstance item = inventory.getItemByObjectId(_itemObjId);
+
+ // attempting to destroy item
+ if (activeChar.getInventory().destroyItemByItemId("ChangeAttribute", _consumeItemId, 1, activeChar, item) == null)
+ {
+ client.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT2);
+ client.sendPacket(ExChangeAttributeFail.STATIC);
+ Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " tried to change attribute without an attribute change crystal.", Config.DEFAULT_PUNISH);
+ return;
+ }
+
+ // get values
+ final int oldElementId = item.getAttackAttributeType().getClientId();
+ final int elementValue = item.getAttackAttribute().getValue();
+ item.clearAllAttributes();
+ item.setAttribute(new AttributeHolder(AttributeType.findByClientId(_newElementId), elementValue));
+
+ // send packets
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S1_S_S2_ATTRIBUTE_HAS_SUCCESSFULLY_CHANGED_TO_S3_ATTRIBUTE);
+ msg.addItemName(item);
+ msg.addAttribute(oldElementId);
+ msg.addAttribute(_newElementId);
+ activeChar.sendPacket(msg);
+ InventoryUpdate iu = new InventoryUpdate();
+ iu.addModifiedItem(item);
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ activeChar.sendPacket(ExChangeAttributeOk.STATIC);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
new file mode 100644
index 0000000000..5aca074929
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/attributechange/SendChangeAttributeTargetItem.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.clientpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.L2GameClient;
+import com.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.attributechange.ExChangeAttributeInfo;
+
+/**
+ * @author Mobius
+ */
+public class SendChangeAttributeTargetItem implements IClientIncomingPacket
+{
+ private int _crystalItemId;
+ private int _itemObjId;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _crystalItemId = packet.readD();
+ _itemObjId = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ final L2PcInstance activeChar = client.getActiveChar();
+ if (activeChar == null)
+ {
+ return;
+ }
+
+ final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(_itemObjId);
+ if ((item == null) || !item.isWeapon())
+ {
+ activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+ return;
+ }
+
+ activeChar.sendPacket(new ExChangeAttributeInfo(_crystalItemId, item));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
new file mode 100644
index 0000000000..81a40c1546
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeFail.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeFail implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeFail();
+
+ public ExChangeAttributeFail()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_FAIL.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
new file mode 100644
index 0000000000..efd669df25
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeInfo.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.enums.AttributeType;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeInfo implements IClientOutgoingPacket
+{
+ private static final Map ATTRIBUTE_MASKS = new HashMap<>();
+ {
+ ATTRIBUTE_MASKS.put(AttributeType.FIRE, (byte) 1);
+ ATTRIBUTE_MASKS.put(AttributeType.WATER, (byte) 2);
+ ATTRIBUTE_MASKS.put(AttributeType.WIND, (byte) 4);
+ ATTRIBUTE_MASKS.put(AttributeType.EARTH, (byte) 8);
+ ATTRIBUTE_MASKS.put(AttributeType.HOLY, (byte) 16);
+ ATTRIBUTE_MASKS.put(AttributeType.DARK, (byte) 32);
+ }
+
+ private final int _crystalItemId;
+ private int _attributes;
+ private int _itemObjId;
+
+ public ExChangeAttributeInfo(int crystalItemId, L2ItemInstance item)
+ {
+ _crystalItemId = crystalItemId;
+ _attributes = 0;
+ for (AttributeType e : AttributeType.ATTRIBUTE_TYPES)
+ {
+ if (e != item.getAttackAttributeType())
+ {
+ _attributes |= ATTRIBUTE_MASKS.get(e);
+ }
+ }
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_INFO.writeId(packet);
+ packet.writeD(_crystalItemId);
+ packet.writeD(_attributes);
+ packet.writeD(_itemObjId);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
new file mode 100644
index 0000000000..4b266e2e33
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeItemList.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.model.ItemInfo;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.AbstractItemPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeItemList extends AbstractItemPacket
+{
+ private final ItemInfo[] _itemsList;
+ private final int _itemId;
+
+ public ExChangeAttributeItemList(int itemId, ItemInfo[] itemsList)
+ {
+ _itemId = itemId;
+ _itemsList = itemsList;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_ITEM_LIST.writeId(packet);
+ packet.writeD(_itemId);
+ packet.writeD(_itemsList.length);
+ for (ItemInfo item : _itemsList)
+ {
+ writeItem(packet, item);
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
new file mode 100644
index 0000000000..5efc5e80e4
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/attributechange/ExChangeAttributeOk.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.l2jmobius.gameserver.network.serverpackets.attributechange;
+
+import com.l2jmobius.commons.network.PacketWriter;
+import com.l2jmobius.gameserver.network.OutgoingPackets;
+import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Mobius
+ */
+public class ExChangeAttributeOk implements IClientOutgoingPacket
+{
+ public static final IClientOutgoingPacket STATIC = new ExChangeAttributeOk();
+
+ public ExChangeAttributeOk()
+ {
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_CHANGE_ATTRIBUTE_OK.writeId(packet);
+ return true;
+ }
+}
\ No newline at end of file