浏览代码

Rework of the enchant system.
All enchant scrolls and support items now defined in one place - AbstractEnchantPacket
Other code reworked and cleaned.
Bug fixed: each support item has different chance increase. Also blessed scrolls does not use support items.
Added check if item was not able to deleted on enchant failure.

_DS_ 16 年之前
父节点
当前提交
d3a6e3e2ba

+ 319 - 0
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/AbstractEnchantPacket.java

@@ -0,0 +1,319 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.network.clientpackets;
+
+import java.util.Map;
+
+import javolution.util.FastMap;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+import net.sf.l2j.gameserver.templates.item.L2Item;
+import net.sf.l2j.gameserver.templates.item.L2WeaponType;
+
+public class AbstractEnchantPacket extends L2GameClientPacket
+{
+
+	public static final Map<Integer, EnchantScroll> _scrolls = new FastMap<Integer, EnchantScroll>();
+	public static final Map<Integer, EnchantItem> _supports = new FastMap<Integer, EnchantItem>();
+
+	public static class EnchantItem
+	{
+		protected final boolean _isWeapon;
+		protected final int _grade;
+		protected final int _maxEnchantLevel;
+		protected final int _chanceAdd;
+
+		public EnchantItem(boolean wep, int type, int level, int chance)
+		{
+			_isWeapon = wep;
+			_grade = type;
+			_maxEnchantLevel = level;
+			_chanceAdd = chance;
+		}
+
+		/*
+		 * Return true if support item can be used for this item 
+		 */
+		public final boolean isValid(L2ItemInstance enchantItem)
+		{
+			if (enchantItem == null)
+				return false;
+			
+			int type2 = enchantItem.getItem().getType2();
+
+			// weapon scrolls can enchant only weapons
+			if (_isWeapon && type2 != L2Item.TYPE2_WEAPON)
+				return false;
+			// armor scrolls can enchant only accessory and armors
+			if (!_isWeapon && (type2 != L2Item.TYPE2_SHIELD_ARMOR && type2 != L2Item.TYPE2_ACCESSORY))
+				return false;
+
+			// check for crystal types
+			switch (enchantItem.getItem().getCrystalType())
+			{
+				case L2Item.CRYSTAL_S:
+				case L2Item.CRYSTAL_S80:
+				case L2Item.CRYSTAL_S84:
+					if (_grade != L2Item.CRYSTAL_S)
+						return false;
+					break;
+				default:
+					if (_grade != enchantItem.getItem().getCrystalType())
+						return false;
+			}
+
+			// check for maximum enchant level
+			if (_maxEnchantLevel != 0 && enchantItem.getEnchantLevel() >= _maxEnchantLevel)
+				return false;
+
+			return true;
+		}
+
+		/*
+		 * return chance increase
+		 */
+		public final int getChanceAdd()
+		{
+			return _chanceAdd;
+		}
+	}
+
+	public static final class EnchantScroll extends EnchantItem
+	{
+		private final boolean _isBlessed;
+		private final boolean _isCrystal;
+		private final boolean _isSafe;
+
+		public EnchantScroll(boolean wep, boolean bless, boolean crystal, boolean safe, int type, int level, int chance)
+		{
+			super(wep, type, level, chance);
+
+			_isBlessed = bless;
+			_isCrystal = crystal;
+			_isSafe = safe;
+		}
+
+		/*
+		 * Return true for blessed scrolls
+		 */
+		public final boolean isBlessed()
+		{
+			return _isBlessed;
+		}
+
+		/*
+		 * Return true for crystal scrolls
+		 */
+		public final boolean isCrystal()
+		{
+			return _isCrystal;
+		}
+
+		/*
+		 * Return true for safe-enchant scrolls (enchant level will remain on failure)
+		 */
+		public final boolean isSafe()
+		{
+			return _isSafe;
+		}
+
+		public final boolean isValid(L2ItemInstance enchantItem, EnchantItem supportItem)
+		{
+			// blessed scrolls can't use support items
+			if (supportItem != null && (!supportItem.isValid(enchantItem) || isBlessed()))
+					return false;
+
+			return isValid(enchantItem);
+		}
+
+		public final int getChance(L2ItemInstance enchantItem, EnchantItem supportItem)
+		{
+			if (!isValid(enchantItem, supportItem))
+				return -1;
+
+			boolean fullBody = enchantItem.getItem().getBodyPart() == L2Item.SLOT_FULL_ARMOR;
+			if (enchantItem.getEnchantLevel() < Config.ENCHANT_SAFE_MAX
+					|| (fullBody && enchantItem.getEnchantLevel() < Config.ENCHANT_SAFE_MAX_FULL))
+				return 100;
+
+			boolean isAccessory = enchantItem.getItem().getType2() == L2Item.TYPE2_ACCESSORY;
+			int chance = 0;
+
+			if (_isBlessed)
+			{
+				// blessed scrolls does not use support items
+				if (supportItem != null)
+					return -1;
+
+				if (_isWeapon)
+					chance = Config.BLESSED_ENCHANT_CHANCE_WEAPON;
+				else if (isAccessory)
+					chance = Config.BLESSED_ENCHANT_CHANCE_JEWELRY;
+				else
+					chance = Config.BLESSED_ENCHANT_CHANCE_ARMOR;
+			}
+			else
+			{
+				if (_isWeapon)
+					chance = Config.ENCHANT_CHANCE_WEAPON;
+				else if (isAccessory)
+					chance = Config.ENCHANT_CHANCE_JEWELRY;
+				else
+					chance = Config.ENCHANT_CHANCE_ARMOR;
+			}
+
+			chance += _chanceAdd;
+
+			if (supportItem != null)
+				chance += supportItem.getChanceAdd();
+
+			return chance;
+		}
+	}
+
+	static
+	{
+		// itemId, (isWeapon, isBlessed, isCrystal, isSafe, grade, max enchant level, chance increase)
+		_scrolls.put(729, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_A, 0, 0));
+		_scrolls.put(730, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_A, 0, 0));
+		_scrolls.put(731, new EnchantScroll(true, false, true, false, L2Item.CRYSTAL_A, 0, 0));
+		_scrolls.put(732, new EnchantScroll(false, false, true, false, L2Item.CRYSTAL_A, 0, 0));
+		_scrolls.put(947, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_B, 0, 0));
+		_scrolls.put(948, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_B, 0, 0));
+		_scrolls.put(949, new EnchantScroll(true, false, true, false, L2Item.CRYSTAL_B, 0, 0));
+		_scrolls.put(950, new EnchantScroll(false, false, true, false, L2Item.CRYSTAL_B, 0, 0));
+		_scrolls.put(951, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_C, 0, 0));
+		_scrolls.put(952, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_C, 0, 0));
+		_scrolls.put(953, new EnchantScroll(true, false, true, false, L2Item.CRYSTAL_C, 0, 0));
+		_scrolls.put(954, new EnchantScroll(false, false, true, false, L2Item.CRYSTAL_C, 0, 0));
+		_scrolls.put(955, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_D, 0, 0));
+		_scrolls.put(956, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_D, 0, 0));
+		_scrolls.put(957, new EnchantScroll(true, false, true, false, L2Item.CRYSTAL_D, 0, 0));
+		_scrolls.put(958, new EnchantScroll(false, false, true, false, L2Item.CRYSTAL_D, 0, 0));
+		_scrolls.put(959, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_S, 0, 0));
+		_scrolls.put(960, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_S, 0, 0));
+		_scrolls.put(961, new EnchantScroll(true, false, true, false, L2Item.CRYSTAL_S, 0, 0));
+		_scrolls.put(962, new EnchantScroll(false, false, true, false, L2Item.CRYSTAL_S, 0, 0));
+		_scrolls.put(6569, new EnchantScroll(true, true, false, false, L2Item.CRYSTAL_A, 0, 0));
+		_scrolls.put(6570, new EnchantScroll(false, true, false, false, L2Item.CRYSTAL_A, 0, 0));
+		_scrolls.put(6571, new EnchantScroll(true, true, false, false, L2Item.CRYSTAL_B, 0, 0));
+		_scrolls.put(6572, new EnchantScroll(false, true, false, false, L2Item.CRYSTAL_B, 0, 0));
+		_scrolls.put(6573, new EnchantScroll(true, true, false, false, L2Item.CRYSTAL_C, 0, 0));
+		_scrolls.put(6574, new EnchantScroll(false, true, false, false, L2Item.CRYSTAL_C, 0, 0));
+		_scrolls.put(6575, new EnchantScroll(true, true, false, false, L2Item.CRYSTAL_D, 0, 0));
+		_scrolls.put(6576, new EnchantScroll(false, true, false, false, L2Item.CRYSTAL_D, 0, 0));
+		_scrolls.put(6577, new EnchantScroll(true, true, false, false, L2Item.CRYSTAL_S, 0, 0));
+		_scrolls.put(6578, new EnchantScroll(false, true, false, false, L2Item.CRYSTAL_S, 0, 0));
+		_scrolls.put(22006, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_D, 0, 10));
+		_scrolls.put(22007, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_C, 0, 10));
+		_scrolls.put(22008, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_B, 0, 10));
+		_scrolls.put(22009, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_A, 0, 10));
+		_scrolls.put(22010, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_D, 0, 10));
+		_scrolls.put(22011, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_C, 0, 10));
+		_scrolls.put(22012, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_B, 0, 10));
+		_scrolls.put(22013, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_A, 0, 10));
+		_scrolls.put(22014, new EnchantScroll(true, false, false, true, L2Item.CRYSTAL_B, 16, 10));
+		_scrolls.put(22015, new EnchantScroll(true, false, false, true, L2Item.CRYSTAL_A, 16, 10));
+		_scrolls.put(22016, new EnchantScroll(false, false, false, true, L2Item.CRYSTAL_B, 16, 10));
+		_scrolls.put(22017, new EnchantScroll(false, false, false, true, L2Item.CRYSTAL_A, 16, 10));
+		_scrolls.put(22018, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_B, 0, 100));
+		_scrolls.put(22019, new EnchantScroll(true, false, false, false, L2Item.CRYSTAL_A, 0, 100));
+		_scrolls.put(22020, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_B, 0, 100));
+		_scrolls.put(22021, new EnchantScroll(false, false, false, false, L2Item.CRYSTAL_A, 0, 100));
+
+		// itemId, (isWeapon, grade, max enchant level, chance increase)
+		_supports.put(12362, new EnchantItem(true, L2Item.CRYSTAL_D, 9, 20));
+		_supports.put(12363, new EnchantItem(true, L2Item.CRYSTAL_C, 9, 18));
+		_supports.put(12364, new EnchantItem(true, L2Item.CRYSTAL_B, 9, 15));
+		_supports.put(12365, new EnchantItem(true, L2Item.CRYSTAL_A, 9, 12));
+		_supports.put(12366, new EnchantItem(true, L2Item.CRYSTAL_S, 9, 10));
+		_supports.put(12367, new EnchantItem(true, L2Item.CRYSTAL_D, 9, 35));
+		_supports.put(12368, new EnchantItem(true, L2Item.CRYSTAL_C, 9, 27));
+		_supports.put(12369, new EnchantItem(true, L2Item.CRYSTAL_B, 9, 23));
+		_supports.put(12370, new EnchantItem(true, L2Item.CRYSTAL_A, 9, 18));
+		_supports.put(12371, new EnchantItem(true, L2Item.CRYSTAL_S, 9, 15));
+	}
+
+	/**
+	 * Return enchant template for scroll
+	 */
+	protected static final EnchantScroll getEnchantScroll(L2ItemInstance scroll)
+	{
+		return _scrolls.get(scroll.getItemId());
+	}
+
+	/**
+	 * Return enchant template for support item 
+	 */
+	protected static final EnchantItem getSupportItem(L2ItemInstance item)
+	{
+		return _supports.get(item.getItemId());
+	}
+
+	/**
+	 * Return true if item can be enchanted 
+	 */
+	protected static final boolean isEnchantable(L2ItemInstance item)
+	{
+		if (item.isHeroItem())
+			return false;
+		if (item.isShadowItem())
+			return false;
+		if (item.isCommonItem())
+			return false;
+		if (item.isEtcItem())
+			return false;
+		if (item.isTimeLimitedItem())
+			return false;
+		if (item.isWear())
+			return false;
+		// rods
+		if (item.getItem().getItemType() == L2WeaponType.ROD)
+			return false;
+		// apprentice and travelers weapons
+		if (item.getItemId() >= 7816 && item.getItemId() <= 7831)
+			return false;
+		// bracelets
+		if (item.getItem().getBodyPart() == L2Item.SLOT_L_BRACELET)
+			return false;
+		if (item.getItem().getBodyPart() == L2Item.SLOT_R_BRACELET)
+			return false;
+		// only items in inventory and equipped can be enchanted
+		if (item.getLocation() != L2ItemInstance.ItemLocation.INVENTORY
+				&& item.getLocation() != L2ItemInstance.ItemLocation.PAPERDOLL)
+			return false;
+		
+		return true;
+	}
+
+	@Override
+	protected void readImpl()
+	{
+
+	}
+
+	@Override
+	protected void runImpl()
+	{
+
+	}
+
+	@Override
+	public String getType()
+	{
+		return "Never Used";
+	}
+}

+ 43 - 378
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java

@@ -26,38 +26,15 @@ import net.sf.l2j.gameserver.network.serverpackets.InventoryUpdate;
 import net.sf.l2j.gameserver.network.serverpackets.ItemList;
 import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
 import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
-import net.sf.l2j.gameserver.templates.item.L2Item;
-import net.sf.l2j.gameserver.templates.item.L2WeaponType;
 import net.sf.l2j.gameserver.util.Util;
 import net.sf.l2j.util.Rnd;
 
-public final class RequestEnchantItem extends L2GameClientPacket
+public final class RequestEnchantItem extends AbstractEnchantPacket
 {
 	protected static final Logger _log = Logger.getLogger(RequestEnchantItem.class.getName());
 
 	private static final String _C__58_REQUESTENCHANTITEM = "[C] 58 RequestEnchantItem";
 
-	private static final int[] ENCHANT_SCROLLS =
-	{
-		729, 730, 947, 948, 951, 952, 955, 956, 959, 960
-	};
-	private static final int[] BLESSED_SCROLLS =
-	{
-		6569, 6570, 6571, 6572, 6573, 6574, 6575, 6576, 6577, 6578
-	};
-	private static final int[] ENCHANT10_SCROLLS =
-	{
-		22006, 22007, 22008, 22009, 22010, 22011, 22012, 22013
-	};
-	private static final int[] BLESSED10_SCROLLS =
-	{
-		22014, 22015, 22016, 22017
-	};
-	private static final int[] ENCHANT100_SCROLLS =
-	{
-		22018, 22019, 22020, 22021
-	};
-
 	private int _objectId = 0;
 
 	@Override
@@ -74,7 +51,7 @@ public final class RequestEnchantItem extends L2GameClientPacket
 		if (activeChar == null || _objectId == 0)
 			return;
 
-		if (activeChar.isOnline() == 0)
+		if (activeChar.isOnline() == 0 || getClient().isDetached())
 		{
 			activeChar.setActiveEnchantItem(null);
 			return;
@@ -97,161 +74,20 @@ public final class RequestEnchantItem extends L2GameClientPacket
 			return;
 		}
 
-		int itemType2 = item.getItem().getType2();
-		boolean enchantItem = false;
-		boolean blessedScroll = false; // item will not break
-		boolean retainEnchantValue = false; // for blessedScroll = true item will retain old enchant value on fail
-		int crystalId = 0;
-
-		/** pretty code ;D */
-		switch (item.getItem().getCrystalType())
-		{
-			case L2Item.CRYSTAL_A:
-				crystalId = 1461;
-				switch (scroll.getItemId())
-				{
-					case 729:
-					case 731:
-					case 6569:
-					case 22009:
-					case 22015:
-					case 22019:
-						if (itemType2 == L2Item.TYPE2_WEAPON)
-							if (support == null || support.getItemId() == 12365)
-								enchantItem = true;
-						break;
-					case 730:
-					case 732:
-					case 6570:
-					case 22013:
-					case 22017:
-					case 22021:
-						if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-							if (support == null || support.getItemId() == 12370)
-								enchantItem = true;
-						break;
-				}
-				break;
-			case L2Item.CRYSTAL_B:
-				crystalId = 1460;
-				switch (scroll.getItemId())
-				{
-					case 947:
-					case 949:
-					case 6571:
-					case 22008:
-					case 22014:
-					case 22018:
-						if (itemType2 == L2Item.TYPE2_WEAPON)
-							if (support == null || support.getItemId() == 12364)
-								enchantItem = true;
-						break;
-					case 948:
-					case 950:
-					case 6572:
-					case 22012:
-					case 22016:
-					case 22020:
-						if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-							if (support == null || support.getItemId() == 12369)
-								enchantItem = true;
-						break;
-				}
-				break;
-			case L2Item.CRYSTAL_C:
-				crystalId = 1459;
-				switch (scroll.getItemId())
-				{
-					case 951:
-					case 953:
-					case 6573:
-					case 22007:
-						if (itemType2 == L2Item.TYPE2_WEAPON)
-							if (support == null || support.getItemId() == 12363)
-								enchantItem = true;
-						break;
-					case 952:
-					case 954:
-					case 6574:
-					case 22011:
-						if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-							if (support == null || support.getItemId() == 12368)
-								enchantItem = true;
-						break;
-				}
-				break;
-			case L2Item.CRYSTAL_D:
-				crystalId = 1458;
-				switch (scroll.getItemId())
-				{
-					case 955:
-					case 957:
-					case 6575:
-					case 22006:
-						if (itemType2 == L2Item.TYPE2_WEAPON)
-							if (support == null || support.getItemId() == 12362)
-								enchantItem = true;
-						break;
-					case 956:
-					case 958:
-					case 6576:
-					case 22010:
-						if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-							if (support == null || support.getItemId() == 12367)
-								enchantItem = true;
-						break;
-				}
-				break;
-			case L2Item.CRYSTAL_S:
-			case L2Item.CRYSTAL_S80:
-			case L2Item.CRYSTAL_S84:
-				crystalId = 1462;
-				switch (scroll.getItemId())
-				{
-					case 959:
-					case 961:
-					case 6577:
-						if (itemType2 == L2Item.TYPE2_WEAPON)
-							if (support == null || support.getItemId() == 12366)
-								enchantItem = true;
-						break;
-					case 960:
-					case 962:
-					case 6578:
-						if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-							if (support == null || support.getItemId() == 12371)
-								enchantItem = true;
-						break;
-				}
-				break;
-		}
-
-		int maxEnchantLevel = 0;
-		switch (itemType2)
-		{
-			case L2Item.TYPE2_WEAPON: 
-				maxEnchantLevel = Config.ENCHANT_MAX_WEAPON;
-				break;
-			case L2Item.TYPE2_SHIELD_ARMOR:
-				maxEnchantLevel = Config.ENCHANT_MAX_ARMOR;
-				break;
-			case L2Item.TYPE2_ACCESSORY:
-				maxEnchantLevel = Config.ENCHANT_MAX_JEWELRY;
-				break;
-		}
-
-		if (maxEnchantLevel != 0 && item.getEnchantLevel() >= maxEnchantLevel)
-			enchantItem = false;
+		// template for scroll
+		EnchantScroll scrollTemplate = getEnchantScroll(scroll);
 
-		// Ancient enchant crystals can enchant only up to 16
-		if (item.getEnchantLevel() >= 16 && scroll.getItemId() >= 22014 && scroll.getItemId() <= 22017)
-			enchantItem = false;
+		// scroll not found in list
+		if (scrollTemplate == null)
+			return;
 
-		// support items can enchant up to 9
-		if (support != null && item.getEnchantLevel() > 9)
-			enchantItem = false;
+		// template for support item, if exist
+		EnchantItem supportTemplate = null;
+		if (support != null)
+			supportTemplate = getSupportItem(support);
 
-		if (!enchantItem)
+		// first validation check
+		if (!scrollTemplate.isValid(item, supportTemplate) || !isEnchantable(item))
 		{
 			activeChar.sendPacket(new SystemMessage(SystemMessageId.INAPPROPRIATE_ENCHANT_CONDITION));
 			activeChar.setActiveEnchantItem(null);
@@ -259,6 +95,7 @@ public final class RequestEnchantItem extends L2GameClientPacket
 			return;
 		}
 
+		// fast auto-enchant cheat check
 		if (activeChar.getActiveEnchantTimestamp() == 0 || System.currentTimeMillis() - activeChar.getActiveEnchantTimestamp() < 2000)
 		{
 			Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " use autoenchant program ", Config.DEFAULT_PUNISH);
@@ -267,6 +104,7 @@ public final class RequestEnchantItem extends L2GameClientPacket
 			return;
 		}
 
+		// attempting to destroy scroll
 		scroll = activeChar.getInventory().destroyItem("Enchant", scroll.getObjectId(), 1, activeChar, item);
 		if (scroll == null)
 		{
@@ -277,6 +115,7 @@ public final class RequestEnchantItem extends L2GameClientPacket
 			return;
 		}
 
+		// attempting to destroy support if exist
 		if (support != null)
 		{
 			support = activeChar.getInventory().destroyItem("Enchant", support.getObjectId(), 1, activeChar, item);
@@ -292,165 +131,14 @@ public final class RequestEnchantItem extends L2GameClientPacket
 
 		SystemMessage sm;
 
-		int chance = 0;
-		maxEnchantLevel = 0;
 		synchronized (item)
 		{
-			if (item.getItem().getType2() == L2Item.TYPE2_WEAPON)
-			{
-				for (int scrollId : ENCHANT_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.ENCHANT_CHANCE_WEAPON;
-						break;
-					}
-				}
-				for (int scrollId : ENCHANT10_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.ENCHANT_CHANCE_WEAPON + 10;
-						break;
-					}
-				}
-				for (int scrollId : BLESSED_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.BLESSED_ENCHANT_CHANCE_WEAPON;
-						blessedScroll = true;
-						break;
-					}
-				}
-				for (int scrollId : BLESSED10_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.BLESSED_ENCHANT_CHANCE_WEAPON + 10;
-						blessedScroll = true;
-						retainEnchantValue = true;
-						break;
-					}
-				}
-				for (int scrollId : ENCHANT100_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = 100;
-						break;
-					}
-				}
-				maxEnchantLevel = Config.ENCHANT_MAX_WEAPON;
-			}
-			else if (item.getItem().getType2() == L2Item.TYPE2_SHIELD_ARMOR)
-			{
-				for (int scrollId : ENCHANT_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.ENCHANT_CHANCE_ARMOR;
-						break;
-					}
-				}
-				for (int scrollId : ENCHANT10_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.ENCHANT_CHANCE_ARMOR + 10;
-						break;
-					}
-				}
-				for (int scrollId : BLESSED_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.BLESSED_ENCHANT_CHANCE_ARMOR;
-						blessedScroll = true;
-						break;
-					}
-				}
-				for (int scrollId : BLESSED10_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.BLESSED_ENCHANT_CHANCE_ARMOR + 10;
-						blessedScroll = true;
-						retainEnchantValue = true;
-						break;
-					}
-				}
-				for (int scrollId : ENCHANT100_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = 100;
-						break;
-					}
-				}
-				maxEnchantLevel = Config.ENCHANT_MAX_ARMOR;
-			}
-			else if (item.getItem().getType2() == L2Item.TYPE2_ACCESSORY)
-			{
-				for (int scrollId : ENCHANT_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.ENCHANT_CHANCE_JEWELRY;
-						break;
-					}
-				}
-				for (int scrollId : ENCHANT10_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.ENCHANT_CHANCE_JEWELRY + 10;
-						break;
-					}
-				}
-				for (int scrollId : BLESSED_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.BLESSED_ENCHANT_CHANCE_JEWELRY;
-						blessedScroll = true;
-						break;
-					}
-				}
-				for (int scrollId : BLESSED10_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = Config.BLESSED_ENCHANT_CHANCE_JEWELRY + 10;
-						blessedScroll = true;
-						retainEnchantValue = true;
-						break;
-					}
-				}
-				for (int scrollId : ENCHANT100_SCROLLS)
-				{
-					if (scroll.getItemId() == scrollId)
-					{
-						chance = 100;
-						break;
-					}
-				}
-				maxEnchantLevel = Config.ENCHANT_MAX_JEWELRY;
-			}
+			int chance = scrollTemplate.getChance(item, supportTemplate);
 
-			// can't enchant rods, hero weapons, adventurers' items,shadow and common items
+			// last validation check
 			if (item.getOwnerId() != activeChar.getObjectId()
-					|| item.getItem().getItemType() == L2WeaponType.ROD
-					|| item.isHeroItem()
-					|| (item.getItemId() >= 7816 && item.getItemId() <= 7831)
-					|| item.isShadowItem()
-					|| item.isCommonItem()
-					|| item.isTimeLimitedItem()
-					|| item.isEtcItem()
-					|| item.isWear()
-					|| item.getItem().getBodyPart() == L2Item.SLOT_L_BRACELET
-					|| item.getItem().getBodyPart() == L2Item.SLOT_R_BRACELET
-					|| (item.getLocation() != L2ItemInstance.ItemLocation.INVENTORY && item.getLocation() != L2ItemInstance.ItemLocation.PAPERDOLL))
+					|| !isEnchantable(item)
+					|| chance < 0)
 			{
 				activeChar.sendPacket(new SystemMessage(SystemMessageId.INAPPROPRIATE_ENCHANT_CONDITION));
 				activeChar.setActiveEnchantItem(null);
@@ -458,40 +146,34 @@ public final class RequestEnchantItem extends L2GameClientPacket
 				return;
 			}
 
-			if (item.getEnchantLevel() < Config.ENCHANT_SAFE_MAX || item.getItem().getBodyPart() == L2Item.SLOT_FULL_ARMOR && item.getEnchantLevel() < Config.ENCHANT_SAFE_MAX_FULL)
-				chance = 100;
-
-			if (support != null && item.getEnchantLevel() <= 9)
-				chance += 20;
-
-			boolean failed = false;
-
 			if (Rnd.get(100) < chance)
 			{
-				if (item.getOwnerId() != activeChar.getObjectId() || (item.getEnchantLevel() >= maxEnchantLevel && maxEnchantLevel != 0))
-				{
-					activeChar.sendPacket(new SystemMessage(SystemMessageId.INAPPROPRIATE_ENCHANT_CONDITION));
-					activeChar.setActiveEnchantItem(null);
-					activeChar.sendPacket(new EnchantResult(2, 0, 0));
-					return;
-				}
-				if (item.getLocation() != L2ItemInstance.ItemLocation.INVENTORY && item.getLocation() != L2ItemInstance.ItemLocation.PAPERDOLL)
-				{
-					activeChar.sendPacket(new SystemMessage(SystemMessageId.INAPPROPRIATE_ENCHANT_CONDITION));
-					activeChar.setActiveEnchantItem(null);
-					activeChar.sendPacket(new EnchantResult(2, 0, 0));
-					return;
-				}
-
+				// success
 				item.setEnchantLevel(item.getEnchantLevel() + 1);
 				item.updateDatabase();
+				activeChar.sendPacket(new EnchantResult(0, 0, 0));
 			}
 			else
 			{
-				failed = true;
+				if (scrollTemplate.isSafe())
+				{
+					// safe enchant - remain old value
+					// need retail message
+					activeChar.sendPacket(new EnchantResult(5, 0, 0));
+				}
+				else if (scrollTemplate.isBlessed())
+				{
+					// blessed enchant - clear enchant value
+					sm = new SystemMessage(SystemMessageId.BLESSED_ENCHANT_FAILED);
+					activeChar.sendPacket(sm);
 
-				if (!blessedScroll)
+					item.setEnchantLevel(0);
+					item.updateDatabase();
+					activeChar.sendPacket(new EnchantResult(3, 0, 0));
+				}
+				else 
 				{
+					// enchant failed, destroy item
 					if (item.isEquipped())
 					{
 						if (item.getEnchantLevel() > 0)
@@ -519,6 +201,7 @@ public final class RequestEnchantItem extends L2GameClientPacket
 						activeChar.broadcastUserInfo();
 					}
 
+					int crystalId = item.getItem().getCrystalItemId();
 					int count = item.getCrystalCount() - (item.getItem().getCrystalCount() + 1) / 2;
 					if (count < 1)
 						count = 1;
@@ -526,7 +209,10 @@ public final class RequestEnchantItem extends L2GameClientPacket
 					L2ItemInstance destroyItem = activeChar.getInventory().destroyItem("Enchant", item, activeChar, null);
 					if (destroyItem == null)
 					{
+						// unable to destroy item, cheater ?
+						Util.handleIllegalPlayerAction(activeChar, "Unable to delete item on enchant failure from player " + activeChar.getName() + ", possible cheater !", Config.DEFAULT_PUNISH);
 						activeChar.setActiveEnchantItem(null);
+						activeChar.sendPacket(new EnchantResult(2, 0, 0));
 						return;
 					}
 
@@ -551,28 +237,10 @@ public final class RequestEnchantItem extends L2GameClientPacket
 					else
 						activeChar.sendPacket(new ItemList(activeChar, true));
 
-					StatusUpdate su = new StatusUpdate(activeChar.getObjectId());
-					su.addAttribute(StatusUpdate.CUR_LOAD, activeChar.getCurrentLoad());
-					activeChar.sendPacket(su);
-
-					activeChar.broadcastUserInfo();
-
 					L2World world = L2World.getInstance();
 					world.removeObject(destroyItem);
 					activeChar.sendPacket(new EnchantResult(1, crystalId, count));
 				}
-				else
-				{
-					sm = new SystemMessage(SystemMessageId.BLESSED_ENCHANT_FAILED);
-					activeChar.sendPacket(sm);
-
-					if (!retainEnchantValue)
-					{
-						item.setEnchantLevel(0);
-						item.updateDatabase();
-					}
-					activeChar.sendPacket(new EnchantResult(2, 0, 0));
-				}
 			}
 			sm = null;
 
@@ -581,9 +249,6 @@ public final class RequestEnchantItem extends L2GameClientPacket
 			activeChar.sendPacket(su);
 			su = null;
 
-			if (!failed)
-				activeChar.sendPacket(new EnchantResult(0, 0, 0));
-
 			activeChar.sendPacket(new ItemList(activeChar, false));
 			activeChar.broadcastUserInfo();
 			activeChar.setActiveEnchantItem(null);

+ 7 - 53
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestExTryToPutEnchantSupportItem.java

@@ -20,13 +20,12 @@ import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.ExPutEnchantSupportItemResult;
 import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
-import net.sf.l2j.gameserver.templates.item.L2Item;
 
 /**
  *
  * @author  KenM
  */
-public class RequestExTryToPutEnchantSupportItem extends L2GameClientPacket
+public class RequestExTryToPutEnchantSupportItem extends AbstractEnchantPacket
 {
 
 	private int _supportObjectId;
@@ -62,60 +61,15 @@ public class RequestExTryToPutEnchantSupportItem extends L2GameClientPacket
 	    {
 	    	if (activeChar.isEnchanting())
 	    	{
-	    		L2ItemInstance supportItem = (L2ItemInstance) L2World.getInstance().findObject(_supportObjectId);
-	    		L2ItemInstance enchantItem = (L2ItemInstance) L2World.getInstance().findObject(_enchantObjectId);
+	    		L2ItemInstance item = (L2ItemInstance) L2World.getInstance().findObject(_enchantObjectId);
+	    		L2ItemInstance support = (L2ItemInstance) L2World.getInstance().findObject(_supportObjectId);
 
-	    		if (supportItem == null || enchantItem == null)
+	    		if (item == null || support == null)
 	    			return;
 
-				int itemType2 = enchantItem.getItem().getType2();
-	    		boolean ok = false;
-
-	    		switch (enchantItem.getItem().getCrystalType())
-	    		{
-	    			case L2Item.CRYSTAL_A:
-	    				if (itemType2 == L2Item.TYPE2_WEAPON && supportItem.getItemId() == 12365)
-	    					ok = true;
-	    				if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-	    					if (supportItem.getItemId() == 12370)
-	    						ok = true;
-	    				break;
-	    			case L2Item.CRYSTAL_B:
-	    				if (itemType2 == L2Item.TYPE2_WEAPON && supportItem.getItemId() == 12364)
-	    					ok = true;
-	    				if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-	    					if (supportItem.getItemId() == 12369)
-	    						ok = true;
-	    				break;
-	    			case L2Item.CRYSTAL_C:
-	    				if (itemType2 == L2Item.TYPE2_WEAPON && supportItem.getItemId() == 12363)
-	    					ok = true;
-	    				if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-	    					if (supportItem.getItemId() == 12368)
-	    						ok = true;
-	    				break;
-	    			case L2Item.CRYSTAL_D:
-	    				if (itemType2 == L2Item.TYPE2_WEAPON && supportItem.getItemId() == 12362)
-	    					ok = true;
-	    				if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-	    					if (supportItem.getItemId() == 12367)
-	    						ok = true;
-	    				break;
-	    			case L2Item.CRYSTAL_S:
-	    			case L2Item.CRYSTAL_S80:
-	    			case L2Item.CRYSTAL_S84:
-	    				if (itemType2 == L2Item.TYPE2_WEAPON && supportItem.getItemId() == 12366)
-	    					ok = true;
-	    				if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-	    					if (supportItem.getItemId() == 12371)
-	    						ok = true;
-	    				break;
-	    		}
-	    		
-	    		if (enchantItem.getEnchantLevel() > 9)
-	    			ok = false;
+	    		EnchantItem supportTemplate = getSupportItem(support);
 	    		
-	    		if (!ok)
+	    		if (supportTemplate == null || !supportTemplate.isValid(item))
 	    		{
 	    			// message may be custom
 	    			activeChar.sendPacket(new SystemMessage(SystemMessageId.INAPPROPRIATE_ENCHANT_CONDITION));
@@ -123,7 +77,7 @@ public class RequestExTryToPutEnchantSupportItem extends L2GameClientPacket
 	    			activeChar.sendPacket(new ExPutEnchantSupportItemResult(0));
 	    			return;
 	    		}
-	    		activeChar.setActiveEnchantSupportItem(supportItem);
+	    		activeChar.setActiveEnchantSupportItem(support);
 				activeChar.sendPacket(new ExPutEnchantSupportItemResult(_supportObjectId));
 	    	}
 	    }

+ 8 - 166
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestExTryToPutEnchantTargetItem.java

@@ -14,21 +14,18 @@
  */
 package net.sf.l2j.gameserver.network.clientpackets;
 
-import net.sf.l2j.Config;
 import net.sf.l2j.gameserver.model.L2ItemInstance;
 import net.sf.l2j.gameserver.model.L2World;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.ExPutEnchantTargetItemResult;
 import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
-import net.sf.l2j.gameserver.templates.item.L2Item;
-import net.sf.l2j.gameserver.templates.item.L2WeaponType;
 
 /**
  *
  * @author  KenM
  */
-public class RequestExTryToPutEnchantTargetItem extends L2GameClientPacket
+public class RequestExTryToPutEnchantTargetItem extends AbstractEnchantPacket
 {
 
 	private int _objectId = 0;
@@ -67,178 +64,23 @@ public class RequestExTryToPutEnchantTargetItem extends L2GameClientPacket
 			if (activeChar.isEnchanting())
 				return;
 
-			L2ItemInstance targetItem = (L2ItemInstance) L2World.getInstance().findObject(_objectId);
-			L2ItemInstance enchantScroll = activeChar.getActiveEnchantItem();
+			L2ItemInstance item = (L2ItemInstance) L2World.getInstance().findObject(_objectId);
+			L2ItemInstance scroll = activeChar.getActiveEnchantItem();
 
-			if (targetItem == null || enchantScroll == null)
+			if (item == null || scroll == null)
 				return;
 
-			activeChar.setIsEnchanting(true);
-
-			switch (targetItem.getLocation())
-			{
-				case INVENTORY:
-				case PAPERDOLL:
-					// can't enchant rods, hero weapons, adventurers' items,shadow and common items
-					if (targetItem.getOwnerId() != activeChar.getObjectId()
-							|| targetItem.getItem().getItemType() == L2WeaponType.ROD
-							|| targetItem.isHeroItem()
-							|| (targetItem.getItemId() >= 7816 && targetItem.getItemId() <= 7831)
-							|| targetItem.isShadowItem()
-							|| targetItem.isCommonItem()
-							|| targetItem.isTimeLimitedItem()
-							|| targetItem.isEtcItem()
-							|| targetItem.isWear()
-							|| targetItem.getItem().getBodyPart() == L2Item.SLOT_L_BRACELET
-							|| targetItem.getItem().getBodyPart() == L2Item.SLOT_R_BRACELET
-							|| (targetItem.getLocation() != L2ItemInstance.ItemLocation.INVENTORY && targetItem.getLocation() != L2ItemInstance.ItemLocation.PAPERDOLL))
-					{
-						activeChar.sendPacket(new SystemMessage(SystemMessageId.DOES_NOT_FIT_SCROLL_CONDITIONS));
-						activeChar.setActiveEnchantItem(null);
-						activeChar.sendPacket(new ExPutEnchantTargetItemResult(0));
-						return;
-					}
-			}
-
-			int itemType2 = targetItem.getItem().getType2();
-			boolean enchantItem = false;
-
-			/** pretty code ;D */
-			switch (targetItem.getItem().getCrystalType())
-			{
-				case L2Item.CRYSTAL_A:
-					switch (enchantScroll.getItemId())
-					{
-						case 729:
-						case 731:
-						case 6569:
-						case 22009:
-						case 22015:
-						case 22019:
-							if (itemType2 == L2Item.TYPE2_WEAPON)
-								enchantItem = true;
-							break;
-						case 730:
-						case 732:
-						case 6570:
-						case 22013:
-						case 22017:
-						case 22021:
-							if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-								enchantItem = true;
-							break;
-					}
-					break;
-				case L2Item.CRYSTAL_B:
-					switch (enchantScroll.getItemId())
-					{
-						case 947:
-						case 949:
-						case 6571:
-						case 22008:
-						case 22014:
-						case 22018:
-							if (itemType2 == L2Item.TYPE2_WEAPON)
-								enchantItem = true;
-							break;
-						case 948:
-						case 950:
-						case 6572:
-						case 22012:
-						case 22016:
-						case 22020:
-							if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-								enchantItem = true;
-							break;
-					}
-					break;
-				case L2Item.CRYSTAL_C:
-					switch (enchantScroll.getItemId())
-					{
-						case 951:
-						case 953:
-						case 6573:
-						case 22007:
-							if (itemType2 == L2Item.TYPE2_WEAPON)
-								enchantItem = true;
-							break;
-						case 952:
-						case 954:
-						case 6574:
-						case 22011:
-							if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-								enchantItem = true;
-							break;
-					}
-					break;
-				case L2Item.CRYSTAL_D:
-					switch (enchantScroll.getItemId())
-					{
-						case 955:
-						case 957:
-						case 6575:
-						case 22006:
-							if (itemType2 == L2Item.TYPE2_WEAPON)
-								enchantItem = true;
-							break;
-						case 956:
-						case 958:
-						case 6576:
-						case 22010:
-							if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-								enchantItem = true;
-							break;
-					}
-					break;
-				case L2Item.CRYSTAL_S:
-				case L2Item.CRYSTAL_S80:
-				case L2Item.CRYSTAL_S84:
-					switch (enchantScroll.getItemId())
-					{
-						case 959:
-						case 961:
-						case 6577:
-							if (itemType2 == L2Item.TYPE2_WEAPON)
-								enchantItem = true;
-							break;
-						case 960:
-						case 962:
-						case 6578:
-							if (itemType2 == L2Item.TYPE2_SHIELD_ARMOR || itemType2 == L2Item.TYPE2_ACCESSORY)
-								enchantItem = true;
-							break;
-					}
-					break;
-			}
+			// template for scroll
+			EnchantScroll scrollTemplate = getEnchantScroll(scroll);
 
-			int maxEnchantLevel = 0;
-			switch (itemType2)
-			{
-				case L2Item.TYPE2_WEAPON: 
-					maxEnchantLevel = Config.ENCHANT_MAX_WEAPON;
-					break;
-				case L2Item.TYPE2_SHIELD_ARMOR:
-					maxEnchantLevel = Config.ENCHANT_MAX_ARMOR;
-					break;
-				case L2Item.TYPE2_ACCESSORY:
-					maxEnchantLevel = Config.ENCHANT_MAX_JEWELRY;
-					break;
-			}
-
-			if (maxEnchantLevel != 0 && targetItem.getEnchantLevel() >= maxEnchantLevel)
-				enchantItem = false;
-
-			// Ancient enchant crystals can enchant only up to 16
-			if (targetItem.getEnchantLevel() >= 16 && enchantScroll.getItemId() >= 22014 && enchantScroll.getItemId() <= 22017)
-				enchantItem = false;
-
-			if (!enchantItem)
+			if (!scrollTemplate.isValid(item) || !isEnchantable(item))
 			{
 				activeChar.sendPacket(new SystemMessage(SystemMessageId.DOES_NOT_FIT_SCROLL_CONDITIONS));
 				activeChar.setActiveEnchantItem(null);
 				activeChar.sendPacket(new ExPutEnchantTargetItemResult(0));
 				return;
 			}
+			activeChar.setIsEnchanting(true);
 			activeChar.setActiveEnchantTimestamp(System.currentTimeMillis());
 			activeChar.sendPacket(new ExPutEnchantTargetItemResult(_objectId));
 		}