Browse Source

BETA: Reworking item enchanting again.
* Renaming enchantData to enchantItemData.
* Renaming enchantOptions to enchantItemOptions.
* isBlessed, isSafe, isWeapon is going to depend on item's type not on attribute over !<scroll element!
* Adding missing check for support item armor/weapon.
* Preventing from getting item enchanted when base scroll chance is 0.
* Note: In retail if u enchant armor to +20 and u use safe enchant scroll to enchant it to +21 it may success but item's enchant isn't changed.
* And some minor code/javadocs changes.
* Thanks to: jurchiks
* Thanks to: Nos

Rumen Nikiforov 11 năm trước cách đây
mục cha
commit
4b9ae1e485

+ 37 - 14
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/EnchantItemData.java

@@ -20,6 +20,7 @@ package com.l2jserver.gameserver.datatables;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.logging.Level;
 
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
@@ -52,7 +53,7 @@ public class EnchantItemData extends DocumentParser
 	{
 		_scrolls.clear();
 		_supports.clear();
-		parseDatapackFile("data/enchantData.xml");
+		parseDatapackFile("data/enchantItemData.xml");
 		_log.info(getClass().getSimpleName() + ": Loaded " + _scrolls.size() + " Enchant Scrolls.");
 		_log.info(getClass().getSimpleName() + ": Loaded " + _supports.size() + " Support Items.");
 	}
@@ -62,6 +63,7 @@ public class EnchantItemData extends DocumentParser
 	{
 		StatsSet set;
 		Node att;
+		NamedNodeMap attrs;
 		for (Node n = getCurrentDocument().getFirstChild(); n != null; n = n.getNextSibling())
 		{
 			if ("list".equalsIgnoreCase(n.getNodeName()))
@@ -70,7 +72,7 @@ public class EnchantItemData extends DocumentParser
 				{
 					if ("enchant".equalsIgnoreCase(d.getNodeName()))
 					{
-						NamedNodeMap attrs = d.getAttributes();
+						attrs = d.getAttributes();
 						set = new StatsSet();
 						for (int i = 0; i < attrs.getLength(); i++)
 						{
@@ -78,20 +80,30 @@ public class EnchantItemData extends DocumentParser
 							set.set(att.getNodeName(), att.getNodeValue());
 						}
 						
-						final EnchantScroll item = new EnchantScroll(set);
-						for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
+						try
 						{
-							if ("item".equalsIgnoreCase(cd.getNodeName()))
+							final EnchantScroll item = new EnchantScroll(set);
+							for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
 							{
-								item.addItem(parseInteger(cd.getAttributes(), "id"));
+								if ("item".equalsIgnoreCase(cd.getNodeName()))
+								{
+									item.addItem(parseInteger(cd.getAttributes(), "id"));
+								}
 							}
+							_scrolls.put(item.getId(), item);
+						}
+						catch (NullPointerException e)
+						{
+							_log.log(Level.WARNING, getClass().getSimpleName() + ": Unexistent enchant scroll: " + set.getString("id") + " defined in enchant data!");
+						}
+						catch (IllegalAccessError e)
+						{
+							_log.log(Level.WARNING, getClass().getSimpleName() + ": Wrong enchant scroll item type: " + set.getString("id") + " defined in enchant data!");
 						}
-						_scrolls.put(item.getId(), item);
 					}
 					else if ("support".equalsIgnoreCase(d.getNodeName()))
 					{
-						NamedNodeMap attrs = d.getAttributes();
-						
+						attrs = d.getAttributes();
 						set = new StatsSet();
 						for (int i = 0; i < attrs.getLength(); i++)
 						{
@@ -99,15 +111,26 @@ public class EnchantItemData extends DocumentParser
 							set.set(att.getNodeName(), att.getNodeValue());
 						}
 						
-						final EnchantItem item = new EnchantItem(set);
-						for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
+						try
 						{
-							if ("item".equalsIgnoreCase(cd.getNodeName()))
+							final EnchantItem item = new EnchantItem(set);
+							for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
 							{
-								item.addItem(parseInteger(cd.getAttributes(), "id"));
+								if ("item".equalsIgnoreCase(cd.getNodeName()))
+								{
+									item.addItem(parseInteger(cd.getAttributes(), "id"));
+								}
 							}
+							_supports.put(item.getId(), item);
+						}
+						catch (NullPointerException e)
+						{
+							_log.log(Level.WARNING, getClass().getSimpleName() + ": Unexistent enchant support item: " + set.getString("id") + " defined in enchant data!");
+						}
+						catch (IllegalAccessError e)
+						{
+							_log.log(Level.WARNING, getClass().getSimpleName() + ": Wrong enchant support item type: " + set.getString("id") + " defined in enchant data!");
 						}
-						_supports.put(item.getId(), item);
 					}
 				}
 			}

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/EnchantItemOptionsData.java

@@ -44,7 +44,7 @@ public class EnchantItemOptionsData extends DocumentParser
 	@Override
 	public synchronized void load()
 	{
-		parseDatapackFile("data/enchantOptions.xml");
+		parseDatapackFile("data/enchantItemOptions.xml");
 	}
 	
 	@Override

+ 60 - 14
L2J_Server_BETA/java/com/l2jserver/gameserver/model/enchant/EnchantItem.java

@@ -26,6 +26,9 @@ import com.l2jserver.gameserver.datatables.ItemTable;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.items.type.L2EtcItemType;
+import com.l2jserver.gameserver.model.items.type.L2ItemType;
+import com.l2jserver.gameserver.util.Util;
 
 /**
  * @author UnAfraid
@@ -34,8 +37,20 @@ public class EnchantItem
 {
 	protected static final Logger _log = Logger.getLogger(EnchantItem.class.getName());
 	
+	private static final L2ItemType[] ENCHANT_TYPES = new L2ItemType[]
+	{
+		L2EtcItemType.ANCIENT_CRYSTAL_ENCHANT_AM,
+		L2EtcItemType.ANCIENT_CRYSTAL_ENCHANT_WP,
+		L2EtcItemType.BLESS_SCRL_ENCHANT_AM,
+		L2EtcItemType.BLESS_SCRL_ENCHANT_WP,
+		L2EtcItemType.SCRL_ENCHANT_AM,
+		L2EtcItemType.SCRL_ENCHANT_WP,
+		L2EtcItemType.SCRL_INC_ENCHANT_PROP_AM,
+		L2EtcItemType.SCRL_INC_ENCHANT_PROP_WP,
+	};
+	
 	private final int _id;
-	private final boolean _isWeapon;
+	protected boolean _isWeapon;
 	private final int _grade;
 	private final int _maxEnchantLevel;
 	private final double _bonusRate;
@@ -44,14 +59,22 @@ public class EnchantItem
 	public EnchantItem(StatsSet set)
 	{
 		_id = set.getInteger("id");
-		_isWeapon = set.getBool("isWeapon", true);
+		if (getItem() == null)
+		{
+			throw new NullPointerException();
+		}
+		else if (!Util.contains(ENCHANT_TYPES, getItem().getItemType()))
+		{
+			throw new IllegalAccessError();
+		}
+		_isWeapon = getItem().getItemType() == L2EtcItemType.SCRL_INC_ENCHANT_PROP_WP;
 		_grade = ItemTable._crystalTypes.get(set.getString("targetGrade", "none"));
 		_maxEnchantLevel = set.getInteger("maxEnchant", 65535);
 		_bonusRate = set.getDouble("bonusRate", 0);
 	}
 	
 	/**
-	 * @return id of current item.
+	 * @return id of current item
 	 */
 	public final int getId()
 	{
@@ -59,14 +82,42 @@ public class EnchantItem
 	}
 	
 	/**
-	 * @return bonus chance that would be added.
+	 * @return bonus chance that would be added
 	 */
 	public final double getBonusRate()
 	{
 		return _bonusRate;
 	}
 	
-	public void addItem(int id)
+	/**
+	 * @return {@link L2Item} current item/scroll
+	 */
+	public final L2Item getItem()
+	{
+		return ItemTable.getInstance().getTemplate(_id);
+	}
+	
+	/**
+	 * @return grade of the item/scroll.
+	 */
+	public final int getGrade()
+	{
+		return _grade;
+	}
+	
+	/**
+	 * @return {@code true} if scroll is for weapon, {@code false} for armor
+	 */
+	public boolean isWeapon()
+	{
+		return _isWeapon;
+	}
+	
+	/**
+	 * Enforces current scroll to use only those items as possible items to enchant
+	 * @param id
+	 */
+	public final void addItem(int id)
 	{
 		if (_itemIds == null)
 		{
@@ -75,14 +126,9 @@ public class EnchantItem
 		_itemIds.add(id);
 	}
 	
-	public boolean verifyItemId(int itemId)
-	{
-		return _itemIds != null ? _itemIds.contains(itemId) : true;
-	}
-	
 	/**
 	 * @param enchantItem
-	 * @return {@code true} if current item is valid to be enchanted, {@code false} otherwise.
+	 * @return {@code true} if current item is valid to be enchanted, {@code false} otherwise
 	 */
 	public final boolean isValid(L2ItemInstance enchantItem)
 	{
@@ -106,7 +152,7 @@ public class EnchantItem
 		{
 			return false;
 		}
-		else if ((enchantItem.isEnchantable() > 1) && !verifyItemId(enchantItem.getId()))
+		else if ((_itemIds != null) && !_itemIds.contains(enchantItem.getId()))
 		{
 			return false;
 		}
@@ -116,9 +162,9 @@ public class EnchantItem
 	
 	/**
 	 * @param type2
-	 * @return {@code true} if current type2 is valid to be enchanted, {@code false} otherwise.
+	 * @return {@code true} if current type2 is valid to be enchanted, {@code false} otherwise
 	 */
-	private boolean isValidItemType(int type2)
+	private final boolean isValidItemType(int type2)
 	{
 		if (type2 == L2Item.TYPE2_WEAPON)
 		{

+ 68 - 24
L2J_Server_BETA/java/com/l2jserver/gameserver/model/enchant/EnchantScroll.java

@@ -24,6 +24,8 @@ import com.l2jserver.gameserver.datatables.EnchantItemGroupsData;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.items.type.L2EtcItemType;
+import com.l2jserver.gameserver.model.items.type.L2ItemType;
 import com.l2jserver.gameserver.network.Debug;
 import com.l2jserver.gameserver.util.Util;
 import com.l2jserver.util.Rnd;
@@ -40,14 +42,16 @@ public final class EnchantScroll extends EnchantItem
 	public EnchantScroll(StatsSet set)
 	{
 		super(set);
-		
-		_isBlessed = set.getBool("isBlessed", false);
-		_isSafe = set.getBool("isSafe", false);
 		_scrollGroupId = set.getInteger("scrollGroupId", 0);
+		
+		final L2ItemType type = getItem().getItemType();
+		_isWeapon = (type == L2EtcItemType.ANCIENT_CRYSTAL_ENCHANT_WP) || (type == L2EtcItemType.BLESS_SCRL_ENCHANT_WP) || (type == L2EtcItemType.SCRL_ENCHANT_WP);
+		_isBlessed = (type == L2EtcItemType.BLESS_SCRL_ENCHANT_AM) || (type == L2EtcItemType.BLESS_SCRL_ENCHANT_WP);
+		_isSafe = (type == L2EtcItemType.ANCIENT_CRYSTAL_ENCHANT_AM) || (type == L2EtcItemType.ANCIENT_CRYSTAL_ENCHANT_WP);
 	}
 	
 	/**
-	 * @return {@code true} for blessed scrolls (enchanted item will remain on failure), {@code false} otherwise.
+	 * @return {@code true} for blessed scrolls (enchanted item will remain on failure), {@code false} otherwise
 	 */
 	public boolean isBlessed()
 	{
@@ -55,7 +59,7 @@ public final class EnchantScroll extends EnchantItem
 	}
 	
 	/**
-	 * @return {@code true} for safe-enchant scrolls (enchant level will remain on failure), {@code false} otherwise.
+	 * @return {@code true} for safe-enchant scrolls (enchant level will remain on failure), {@code false} otherwise
 	 */
 	public boolean isSafe()
 	{
@@ -63,7 +67,7 @@ public final class EnchantScroll extends EnchantItem
 	}
 	
 	/**
-	 * @return id of scroll group that should be used.
+	 * @return id of scroll group that should be used
 	 */
 	public int getScrollGroupId()
 	{
@@ -73,14 +77,25 @@ public final class EnchantScroll extends EnchantItem
 	/**
 	 * @param enchantItem
 	 * @param supportItem
-	 * @return {@code true} if current scroll is valid to be used with support item, {@code false} otherwise.
+	 * @return {@code true} if current scroll is valid to be used with support item, {@code false} otherwise
 	 */
 	public boolean isValid(L2ItemInstance enchantItem, EnchantItem supportItem)
 	{
-		// blessed scrolls can't use support items
-		if ((supportItem != null) && (!supportItem.isValid(enchantItem) || isBlessed()))
+		if ((supportItem != null))
 		{
-			return false;
+			// blessed scrolls can't use support items
+			if (isBlessed())
+			{
+				return false;
+			}
+			if (!supportItem.isValid(enchantItem))
+			{
+				return false;
+			}
+			else if (supportItem.isWeapon() != _isWeapon)
+			{
+				return false;
+			}
 		}
 		
 		return super.isValid(enchantItem);
@@ -89,43 +104,72 @@ public final class EnchantScroll extends EnchantItem
 	/**
 	 * @param player
 	 * @param enchantItem
-	 * @param supportItem
-	 * @return the total chance for success rate of this scroll.
+	 * @return the chance of current scroll's group.
 	 */
-	public EnchantResultType calculateSuccess(L2PcInstance player, L2ItemInstance enchantItem, EnchantItem supportItem)
+	public double getChance(L2PcInstance player, L2ItemInstance enchantItem)
 	{
-		if (!isValid(enchantItem, supportItem))
-		{
-			return EnchantResultType.ERROR;
-		}
-		
 		if (EnchantItemGroupsData.getInstance().getScrollGroup(_scrollGroupId) == null)
 		{
 			_log.log(Level.WARNING, getClass().getSimpleName() + ": Unexistent enchant scroll group specified for enchant scroll: " + getId());
-			return EnchantResultType.ERROR;
+			return -1;
 		}
 		
 		final EnchantItemGroup group = EnchantItemGroupsData.getInstance().getItemGroup(enchantItem.getItem(), _scrollGroupId);
 		if (group == null)
 		{
 			_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't find enchant item group for scroll: " + getId() + " requested by: " + player);
+			return -1;
+		}
+		return group.getChance(enchantItem.getEnchantLevel());
+	}
+	
+	/**
+	 * @param player
+	 * @param enchantItem
+	 * @param supportItem
+	 * @return the total chance for success rate of this scroll
+	 */
+	public EnchantResultType calculateSuccess(L2PcInstance player, L2ItemInstance enchantItem, EnchantItem supportItem)
+	{
+		if (!isValid(enchantItem, supportItem))
+		{
+			return EnchantResultType.ERROR;
+		}
+		
+		final double chance = getChance(player, enchantItem);
+		if (chance == -1)
+		{
 			return EnchantResultType.ERROR;
 		}
 		
-		final double chance = group.getChance(enchantItem.getEnchantLevel());
 		final double bonusRate = getBonusRate();
-		final double supportBonusRate = ((supportItem != null) && !_isBlessed) ? supportItem.getBonusRate() : 0;
-		final double finalChance = chance + bonusRate + supportBonusRate;
+		final double supportBonusRate = (supportItem != null) ? supportItem.getBonusRate() : 0;
+		final double finalChance = Math.min(chance + bonusRate + supportBonusRate, 100);
 		
 		final double random = 100 * Rnd.nextDouble();
 		final boolean success = (random < finalChance);
 		
 		if (player.isDebug())
 		{
+			final EnchantItemGroup group = EnchantItemGroupsData.getInstance().getItemGroup(enchantItem.getItem(), _scrollGroupId);
 			final StatsSet set = new StatsSet();
+			if (isBlessed())
+			{
+				set.set("isBlessed", isBlessed());
+			}
+			if (isSafe())
+			{
+				set.set("isSafe", isSafe());
+			}
 			set.set("chance", Util.formatDouble(chance, "#.##"));
-			set.set("bonusRate", Util.formatDouble(bonusRate, "#.##"));
-			set.set("supportBonusRate", Util.formatDouble(supportBonusRate, "#.##"));
+			if (bonusRate > 0)
+			{
+				set.set("bonusRate", Util.formatDouble(bonusRate, "#.##"));
+			}
+			if (supportBonusRate > 0)
+			{
+				set.set("supportBonusRate", Util.formatDouble(supportBonusRate, "#.##"));
+			}
 			set.set("finalChance", Util.formatDouble(finalChance, "#.##"));
 			set.set("random", Util.formatDouble(random, "#.##"));
 			set.set("success", success);

+ 7 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestEnchantItem.java

@@ -93,7 +93,7 @@ public final class RequestEnchantItem extends L2GameClientPacket
 		}
 		
 		// template for scroll
-		EnchantScroll scrollTemplate = EnchantItemData.getInstance().getEnchantScroll(scroll);
+		final EnchantScroll scrollTemplate = EnchantItemData.getInstance().getEnchantScroll(scroll);
 		
 		// scroll not found in list
 		if (scrollTemplate == null)
@@ -180,9 +180,12 @@ public final class RequestEnchantItem extends L2GameClientPacket
 				{
 					L2Skill enchant4Skill = null;
 					L2Item it = item.getItem();
-					
-					item.setEnchantLevel(item.getEnchantLevel() + 1);
-					item.updateDatabase();
+					// Increase enchant level only if scroll's base template has chance, some armors can success over +20 but they shouldn't have increased.
+					if (scrollTemplate.getChance(activeChar, item) > 0)
+					{
+						item.setEnchantLevel(item.getEnchantLevel() + 1);
+						item.updateDatabase();
+					}
 					activeChar.sendPacket(new EnchantResult(0, 0, 0));
 					
 					if (Config.LOG_ITEM_ENCHANTS)