Переглянути джерело

Enchant Skill Tree rework. Some parts created by JIV.

Gigiikun 15 роки тому
батько
коміт
f1bb598dab
16 змінених файлів з 533 додано та 402 видалено
  1. 2 0
      L2_GameServer/java/com/l2jserver/gameserver/GameServer.java
  2. 238 0
      L2_GameServer/java/com/l2jserver/gameserver/datatables/EnchantGroupsTable.java
  3. 1 0
      L2_GameServer/java/com/l2jserver/gameserver/datatables/SkillTable.java
  4. 18 133
      L2_GameServer/java/com/l2jserver/gameserver/datatables/SkillTreeTable.java
  5. 106 0
      L2_GameServer/java/com/l2jserver/gameserver/model/L2EnchantSkillGroup.java
  6. 98 179
      L2_GameServer/java/com/l2jserver/gameserver/model/L2EnchantSkillLearn.java
  7. 2 1
      L2_GameServer/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
  8. 7 7
      L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkill.java
  9. 2 2
      L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillInfo.java
  10. 2 2
      L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillInfoDetail.java
  11. 5 5
      L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillRouteChange.java
  12. 7 7
      L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillSafe.java
  13. 5 5
      L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillUntrain.java
  14. 11 19
      L2_GameServer/java/com/l2jserver/gameserver/network/serverpackets/ExEnchantSkillInfo.java
  15. 12 26
      L2_GameServer/java/com/l2jserver/gameserver/network/serverpackets/ExEnchantSkillInfoDetail.java
  16. 17 16
      L2_GameServer/java/com/l2jserver/gameserver/skills/DocumentSkill.java

+ 2 - 0
L2_GameServer/java/com/l2jserver/gameserver/GameServer.java

@@ -43,6 +43,7 @@ import com.l2jserver.gameserver.datatables.CharNameTable;
 import com.l2jserver.gameserver.datatables.CharTemplateTable;
 import com.l2jserver.gameserver.datatables.CharTemplateTable;
 import com.l2jserver.gameserver.datatables.ClanTable;
 import com.l2jserver.gameserver.datatables.ClanTable;
 import com.l2jserver.gameserver.datatables.DoorTable;
 import com.l2jserver.gameserver.datatables.DoorTable;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.EnchantHPBonusData;
 import com.l2jserver.gameserver.datatables.EnchantHPBonusData;
 import com.l2jserver.gameserver.datatables.EventDroplist;
 import com.l2jserver.gameserver.datatables.EventDroplist;
 import com.l2jserver.gameserver.datatables.ExtractableItemsData;
 import com.l2jserver.gameserver.datatables.ExtractableItemsData;
@@ -198,6 +199,7 @@ public class GameServer
 		
 		
 		// keep the references of Singletons to prevent garbage collection
 		// keep the references of Singletons to prevent garbage collection
 		CharNameTable.getInstance();
 		CharNameTable.getInstance();
+		EnchantGroupsTable.getInstance();
 		SkillTable.getInstance();
 		SkillTable.getInstance();
 		
 		
 		ItemTable.getInstance();
 		ItemTable.getInstance();

+ 238 - 0
L2_GameServer/java/com/l2jserver/gameserver/datatables/EnchantGroupsTable.java

@@ -0,0 +1,238 @@
+/*
+ * 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 com.l2jserver.gameserver.datatables;
+
+import gnu.trove.TIntObjectHashMap;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jserver.L2DatabaseFactory;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup;
+import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
+import com.l2jserver.gameserver.model.L2Skill;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.13.2.2.2.8 $ $Date: 2005/04/06 16:13:25 $
+ */
+public class EnchantGroupsTable
+{
+	public static final int NORMAL_ENCHANT_COST_MULTIPLIER = 1;
+	public static final int SAFE_ENCHANT_COST_MULTIPLIER = 5;
+	
+	public static final int NORMAL_ENCHANT_BOOK = 6622;
+	public static final int SAFE_ENCHANT_BOOK = 9627;
+	public static final int CHANGE_ENCHANT_BOOK = 9626;
+	public static final int UNTRAIN_ENCHANT_BOOK = 9625;
+	
+	private static Logger _log = Logger.getLogger(EnchantGroupsTable.class.getName());
+	
+	private TIntObjectHashMap<L2EnchantSkillGroup> _enchantSkillGroups; //enchant skill group
+	private TIntObjectHashMap<L2EnchantSkillLearn> _enchantSkillTrees; //enchant skill list
+	
+	public static EnchantGroupsTable getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	
+	private EnchantGroupsTable()
+	{
+		load();
+	}
+	
+	private void load()
+	{
+		int count = 0;
+		Connection con = null;
+		
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			try
+			{
+				_enchantSkillGroups = new TIntObjectHashMap<L2EnchantSkillGroup>();
+				_enchantSkillTrees = new TIntObjectHashMap<L2EnchantSkillLearn>();
+				
+				PreparedStatement statement = con.prepareStatement("SELECT group_id, level, adena, exp, sp, success_rate76, success_rate77, success_rate78, success_rate79, success_rate80, success_rate81, success_rate82, success_rate83, success_rate84, success_rate85 FROM enchant_skill_groups ORDER BY group_id, level");
+				ResultSet enchantGroups = statement.executeQuery();
+				
+				int prevGroupId = -1;
+				
+				while (enchantGroups.next())
+				{
+					int id = enchantGroups.getInt("group_id");
+					int lvl = enchantGroups.getInt("level");
+					int adena = enchantGroups.getInt("adena");
+					int exp = enchantGroups.getInt("exp");
+					int sp = enchantGroups.getInt("sp");
+					byte rate76 = enchantGroups.getByte("success_rate76");
+					byte rate77 = enchantGroups.getByte("success_rate77");
+					byte rate78 = enchantGroups.getByte("success_rate78");
+					byte rate79 = enchantGroups.getByte("success_rate79");
+					byte rate80 = enchantGroups.getByte("success_rate80");
+					byte rate81 = enchantGroups.getByte("success_rate81");
+					byte rate82 = enchantGroups.getByte("success_rate82");
+					byte rate83 = enchantGroups.getByte("success_rate83");
+					byte rate84 = enchantGroups.getByte("success_rate84");
+					byte rate85 = enchantGroups.getByte("success_rate85");
+					
+					if (prevGroupId != id)
+						prevGroupId = id;
+					
+					L2EnchantSkillGroup group = _enchantSkillGroups.get(id);
+					if (group == null)
+					{
+						group = new L2EnchantSkillGroup(id);
+						_enchantSkillGroups.put(id, group);
+						count++;
+					}
+					EnchantSkillDetail esd = new EnchantSkillDetail(lvl, adena, exp, sp, rate76, rate77, rate78, rate79, rate80, rate81, rate82, rate83, rate84, rate85);
+					group.addEnchantDetail(esd);
+				}
+				
+				enchantGroups.close();
+				statement.close();
+			}
+			catch (Exception e)
+			{
+				_log.log(Level.SEVERE, "Error while loading enchant skill groups ", e);
+			}
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.SEVERE, "Error while loading enchant skill groups ", e);
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+		
+		_log.config("EnchantGroupsTable: Loaded " + count + " groups.");
+	}
+	
+	public int addNewRouteForSkill(int skillId, int maxLvL, int route, int group)
+	{
+		L2EnchantSkillLearn enchantableSkill = _enchantSkillTrees.get(skillId);
+		if (enchantableSkill == null)
+		{
+			enchantableSkill = new L2EnchantSkillLearn(skillId, maxLvL);
+			_enchantSkillTrees.put(skillId, enchantableSkill);
+		}
+		if (_enchantSkillGroups.containsKey(group))
+		{
+			enchantableSkill.addNewEnchantRoute(route, group);
+			
+			return _enchantSkillGroups.get(group).getEnchantGroupDetails().size();
+		}
+		_log.log(Level.SEVERE, "Error while loading generating enchant skill id: " + skillId + "; route: " + route + "; missing group: " + group);
+		return 0;
+	}
+	
+	public L2EnchantSkillLearn getSkillEnchantmentForSkill(L2Skill skill)
+	{
+		L2EnchantSkillLearn esl = this.getSkillEnchantmentBySkillId(skill.getId());
+		// there is enchantment for this skill and we have the required level of it
+		if (esl != null && skill.getLevel() >= esl.getBaseLevel())
+		{
+			return esl;
+		}
+		return null;
+	}
+	
+	public L2EnchantSkillLearn getSkillEnchantmentBySkillId(int skillId)
+	{
+		return _enchantSkillTrees.get(skillId);
+	}
+	
+	public int getEnchantSkillSpCost(L2Skill skill)
+	{
+		L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
+		if (enchantSkillLearn != null)
+		{
+			
+			EnchantSkillDetail esd = enchantSkillLearn.getEnchantSkillDetail(skill.getLevel());
+			if (esd != null)
+			{
+				return esd.getSpCost();
+			}
+		}
+		
+		return Integer.MAX_VALUE;
+	}
+	
+	public int getEnchantSkillAdenaCost(L2Skill skill)
+	{
+		L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
+		if (enchantSkillLearn != null)
+		{
+			EnchantSkillDetail esd = enchantSkillLearn.getEnchantSkillDetail(skill.getLevel());
+			if (esd != null)
+			{
+				return esd.getAdenaCost();
+			}
+		}
+		
+		return Integer.MAX_VALUE;
+	}
+	
+	public byte getEnchantSkillRate(L2PcInstance player, L2Skill skill)
+	{
+		L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
+		if (enchantSkillLearn != null)
+		{
+			EnchantSkillDetail esd = enchantSkillLearn.getEnchantSkillDetail(skill.getLevel());
+			if (esd != null)
+			{
+				return esd.getRate(player);
+			}
+		}
+		
+		return 0;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final EnchantGroupsTable _instance = new EnchantGroupsTable();
+	}
+
+	/**
+	 * @return L2EnchantSkillGroup
+	 */
+	public L2EnchantSkillGroup getEnchantSkillGroupById(int id)
+	{
+		return _enchantSkillGroups.get(id);
+	}
+	
+	public void reload()
+	{
+		load();
+	}
+}

+ 1 - 0
L2_GameServer/java/com/l2jserver/gameserver/datatables/SkillTable.java

@@ -53,6 +53,7 @@ public class SkillTable
 			if (skillLvl > maxLvl)
 			if (skillLvl > maxLvl)
 				_skillMaxLevel.put(skillId, skillLvl);
 				_skillMaxLevel.put(skillId, skillLvl);
 		}
 		}
+		//SkillTreeTable.getInstance().reload();
 		
 		
 		// Reloading as well FrequentSkill enumeration values 
 		// Reloading as well FrequentSkill enumeration values 
 		for (FrequentSkill sk : FrequentSkill.values())
 		for (FrequentSkill sk : FrequentSkill.values())

+ 18 - 133
L2_GameServer/java/com/l2jserver/gameserver/datatables/SkillTreeTable.java

@@ -24,12 +24,10 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
 import com.l2jserver.L2DatabaseFactory;
 import com.l2jserver.L2DatabaseFactory;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2PledgeSkillLearn;
 import com.l2jserver.gameserver.model.L2PledgeSkillLearn;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2SkillLearn;
 import com.l2jserver.gameserver.model.L2SkillLearn;
 import com.l2jserver.gameserver.model.L2TransformSkillLearn;
 import com.l2jserver.gameserver.model.L2TransformSkillLearn;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn.EnchantSkillDetail;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.base.ClassId;
 import com.l2jserver.gameserver.model.base.ClassId;
 
 
@@ -43,22 +41,12 @@ import javolution.util.FastMap;
  */
  */
 public class SkillTreeTable
 public class SkillTreeTable
 {
 {
-	public static final int NORMAL_ENCHANT_COST_MULTIPLIER = 1;
-	public static final int SAFE_ENCHANT_COST_MULTIPLIER = 5;
-	public static final int ADENA_XP_DIV = 3; //TODO magic number
-	
-	public static final int NORMAL_ENCHANT_BOOK = 6622;
-	public static final int SAFE_ENCHANT_BOOK = 9627;
-	public static final int CHANGE_ENCHANT_BOOK = 9626;
-	public static final int UNTRAIN_ENCHANT_BOOK = 9625;
-	
 	private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
 	private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
 	
 	
 	private Map<ClassId, Map<Integer, L2SkillLearn>> _skillTrees;
 	private Map<ClassId, Map<Integer, L2SkillLearn>> _skillTrees;
 	private List<L2SkillLearn> _fishingSkillTrees; //all common skills (teached by Fisherman)
 	private List<L2SkillLearn> _fishingSkillTrees; //all common skills (teached by Fisherman)
 	private List<L2SkillLearn> _expandDwarfCraftSkillTrees; //list of special skill for dwarf (expand dwarf craft) learned by class teacher
 	private List<L2SkillLearn> _expandDwarfCraftSkillTrees; //list of special skill for dwarf (expand dwarf craft) learned by class teacher
 	private List<L2PledgeSkillLearn> _pledgeSkillTrees; //pledge skill list
 	private List<L2PledgeSkillLearn> _pledgeSkillTrees; //pledge skill list
-	private Map<Integer, L2EnchantSkillLearn> _enchantSkillTrees; //enchant skill list
 	private List<L2TransformSkillLearn> _TransformSkillTrees; // Transform Skills (Test)
 	private List<L2TransformSkillLearn> _TransformSkillTrees; // Transform Skills (Test)
 	private FastList<L2SkillLearn> _specialSkillTrees;
 	private FastList<L2SkillLearn> _specialSkillTrees;
 	
 	
@@ -67,6 +55,12 @@ public class SkillTreeTable
 		return SingletonHolder._instance;
 		return SingletonHolder._instance;
 	}
 	}
 	
 	
+	
+	private SkillTreeTable()
+	{
+		load();
+	}
+	
 	/**
 	/**
 	 * Return the minimum level needed to have this Expertise.<BR><BR>
 	 * Return the minimum level needed to have this Expertise.<BR><BR>
 	 *
 	 *
@@ -128,7 +122,7 @@ public class SkillTreeTable
 		return 0;
 		return 0;
 	}
 	}
 	
 	
-	private SkillTreeTable()
+	private void load()
 	{
 	{
 		int classId = 0;
 		int classId = 0;
 		int count = 0;
 		int count = 0;
@@ -137,7 +131,6 @@ public class SkillTreeTable
 		int count4 = 0;
 		int count4 = 0;
 		int count5 = 0;
 		int count5 = 0;
 		int count6 = 0;
 		int count6 = 0;
-		int count7 = 0;
 		Connection con = null;
 		Connection con = null;
 		
 		
 		try
 		try
@@ -246,57 +239,6 @@ public class SkillTreeTable
 				_log.severe("Error while creating fishing skill table: " + e);
 				_log.severe("Error while creating fishing skill table: " + e);
 			}
 			}
 			
 			
-			try
-			{
-				_enchantSkillTrees = new FastMap<Integer, L2EnchantSkillLearn>();
-				
-				PreparedStatement statement = con.prepareStatement("SELECT skill_id, level, base_lvl, sp, min_skill_lvl, exp, success_rate76, success_rate77, success_rate78, success_rate79, success_rate80, success_rate81, success_rate82, success_rate83, success_rate84, success_rate85 FROM enchant_skill_trees ORDER BY skill_id, level");
-				ResultSet skilltree3 = statement.executeQuery();
-				
-				int prevSkillId = -1;
-				
-				while (skilltree3.next())
-				{
-					int id = skilltree3.getInt("skill_id");
-					int lvl = skilltree3.getInt("level");
-					int baseLvl = skilltree3.getInt("base_lvl");
-					int minSkillLvl = skilltree3.getInt("min_skill_lvl");
-					int sp = skilltree3.getInt("sp");
-					int exp = skilltree3.getInt("exp");
-					byte rate76 = skilltree3.getByte("success_rate76");
-					byte rate77 = skilltree3.getByte("success_rate77");
-					byte rate78 = skilltree3.getByte("success_rate78");
-					byte rate79 = skilltree3.getByte("success_rate79");
-					byte rate80 = skilltree3.getByte("success_rate80");
-					byte rate81 = skilltree3.getByte("success_rate81");
-					byte rate82 = skilltree3.getByte("success_rate82");
-					byte rate83 = skilltree3.getByte("success_rate83");
-					byte rate84 = skilltree3.getByte("success_rate84");
-					byte rate85 = skilltree3.getByte("success_rate85");
-					
-					if (prevSkillId != id)
-						prevSkillId = id;
-					
-					L2EnchantSkillLearn skill = _enchantSkillTrees.get(id);
-					if (skill == null)
-					{
-						skill = new L2EnchantSkillLearn(id, baseLvl);
-						_enchantSkillTrees.put(id, skill);
-					}
-					EnchantSkillDetail esd = new EnchantSkillDetail(lvl, minSkillLvl, sp, exp, rate76, rate77, rate78, rate79, rate80, rate81, rate82, rate83, rate84, rate85);
-					skill.addEnchantDetail(esd);
-				}
-				
-				skilltree3.close();
-				statement.close();
-				
-				count4 = _enchantSkillTrees.size();
-			}
-			catch (Exception e)
-			{
-				_log.log(Level.SEVERE, "Error while creating enchant skill table ", e);
-			}
-			
 			try
 			try
 			{
 			{
 				_pledgeSkillTrees = new FastList<L2PledgeSkillLearn>();
 				_pledgeSkillTrees = new FastList<L2PledgeSkillLearn>();
@@ -327,7 +269,7 @@ public class SkillTreeTable
 				skilltree4.close();
 				skilltree4.close();
 				statement.close();
 				statement.close();
 				
 				
-				count5 = _pledgeSkillTrees.size();
+				count4 = _pledgeSkillTrees.size();
 			}
 			}
 			catch (Exception e)
 			catch (Exception e)
 			{
 			{
@@ -363,7 +305,7 @@ public class SkillTreeTable
 				skilltree5.close();
 				skilltree5.close();
 				statement.close();
 				statement.close();
 				
 				
-				count6 = _TransformSkillTrees.size();
+				count5 = _TransformSkillTrees.size();
 			}
 			}
 			catch (Exception e)
 			catch (Exception e)
 			{
 			{
@@ -397,7 +339,7 @@ public class SkillTreeTable
 				skilltree6.close();
 				skilltree6.close();
 				statement.close();
 				statement.close();
 				
 				
-				count7 = _specialSkillTrees.size();
+				count6 = _specialSkillTrees.size();
 			}
 			}
 			catch (Exception e)
 			catch (Exception e)
 			{
 			{
@@ -421,10 +363,9 @@ public class SkillTreeTable
 		
 		
 		_log.config("FishingSkillTreeTable: Loaded " + count2 + " general skills.");
 		_log.config("FishingSkillTreeTable: Loaded " + count2 + " general skills.");
 		_log.config("DwarvenCraftSkillTreeTable: Loaded " + count3 + " dwarven skills.");
 		_log.config("DwarvenCraftSkillTreeTable: Loaded " + count3 + " dwarven skills.");
-		_log.config("EnchantSkillTreeTable: Loaded " + count4 + " enchant skills.");
-		_log.config("PledgeSkillTreeTable: Loaded " + count5 + " pledge skills");
-		_log.config("TransformSkillTreeTable: Loaded " + count6 + " transform skills");
-		_log.config("SpecialSkillTreeTable: Loaded " + count7 + " special skills");
+		_log.config("PledgeSkillTreeTable: Loaded " + count4 + " pledge skills");
+		_log.config("TransformSkillTreeTable: Loaded " + count5 + " transform skills");
+		_log.config("SpecialSkillTreeTable: Loaded " + count6 + " special skills");
 	}
 	}
 	
 	
 	private Map<ClassId, Map<Integer, L2SkillLearn>> getSkillTrees()
 	private Map<ClassId, Map<Integer, L2SkillLearn>> getSkillTrees()
@@ -576,22 +517,6 @@ public class SkillTreeTable
 		return result.toArray(new L2SkillLearn[result.size()]);
 		return result.toArray(new L2SkillLearn[result.size()]);
 	}
 	}
 	
 	
-	public L2EnchantSkillLearn getSkillEnchantmentForSkill(L2Skill skill)
-	{
-		L2EnchantSkillLearn esl = this.getSkillEnchantmentBySkillId(skill.getId());
-		// there is enchantment for this skill and we have the required level of it
-		if (esl != null && skill.getLevel() >= esl.getBaseLevel())
-		{
-			return esl;
-		}
-		return null;
-	}
-	
-	public L2EnchantSkillLearn getSkillEnchantmentBySkillId(int skillId)
-	{
-		return _enchantSkillTrees.get(skillId);
-	}
-	
 	public L2TransformSkillLearn[] getAvailableTransformSkills(L2PcInstance cha)
 	public L2TransformSkillLearn[] getAvailableTransformSkills(L2PcInstance cha)
 	{
 	{
 		List<L2TransformSkillLearn> result = new FastList<L2TransformSkillLearn>();
 		List<L2TransformSkillLearn> result = new FastList<L2TransformSkillLearn>();
@@ -789,54 +714,14 @@ public class SkillTreeTable
 		return skillCost;
 		return skillCost;
 	}
 	}
 	
 	
-	public int getEnchantSkillSpCost(L2Skill skill)
-	{
-		L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
-		if (enchantSkillLearn != null)
-		{
-			EnchantSkillDetail esd = enchantSkillLearn.getEnchantSkillDetail(skill.getLevel());
-			if (esd != null)
-			{
-				return esd.getSpCost();
-			}
-		}
-		
-		return Integer.MAX_VALUE;
-	}
-	
-	public int getEnchantSkillAdenaCost(L2Skill skill)
-	{
-		L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
-		if (enchantSkillLearn != null)
-		{
-			EnchantSkillDetail esd = enchantSkillLearn.getEnchantSkillDetail(skill.getLevel());
-			if (esd != null)
-			{
-				return esd.getAdena();
-			}
-		}
-		
-		return Integer.MAX_VALUE;
-	}
-	
-	public byte getEnchantSkillRate(L2PcInstance player, L2Skill skill)
-	{
-		L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
-		if (enchantSkillLearn != null)
-		{
-			EnchantSkillDetail esd = enchantSkillLearn.getEnchantSkillDetail(skill.getLevel());
-			if (esd != null)
-			{
-				return esd.getRate(player);
-			}
-		}
-		
-		return 0;
-	}
-	
 	@SuppressWarnings("synthetic-access")
 	@SuppressWarnings("synthetic-access")
 	private static class SingletonHolder
 	private static class SingletonHolder
 	{
 	{
 		protected static final SkillTreeTable _instance = new SkillTreeTable();
 		protected static final SkillTreeTable _instance = new SkillTreeTable();
 	}
 	}
+	
+	public void reload()
+	{
+		load();
+	}
 }
 }

+ 106 - 0
L2_GameServer/java/com/l2jserver/gameserver/model/L2EnchantSkillGroup.java

@@ -0,0 +1,106 @@
+/*
+ * 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 com.l2jserver.gameserver.model;
+
+import java.util.List;
+
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+
+import javolution.util.FastList;
+
+public final class L2EnchantSkillGroup
+{
+	private final int _id;
+	private List<EnchantSkillDetail> _enchantDetails = new FastList<EnchantSkillDetail>();
+
+	public L2EnchantSkillGroup(int id)
+	{
+		_id = id;
+	}
+
+	public void addEnchantDetail(EnchantSkillDetail detail)
+	{
+		_enchantDetails.add(detail);
+	}
+	
+	public int getId()
+	{
+		return _id;
+	}
+	
+	public List<EnchantSkillDetail> getEnchantGroupDetails()
+	{
+		return _enchantDetails;
+	}
+	
+	public static class EnchantSkillDetail
+	{
+		private final int _level;
+		private final int _adenaCost;
+		private final int _expCost;
+		private final int _spCost;
+		private final byte[] _rate;
+		
+		public EnchantSkillDetail(int lvl, int adena, int exp, int sp, byte rate76, byte rate77, byte rate78, byte rate79, byte rate80, byte rate81, byte rate82, byte rate83, byte rate84, byte rate85)
+		{
+			_level = lvl;
+			_adenaCost = adena;
+			_expCost = exp;
+			_spCost = sp;
+			_rate = new byte[10];
+			_rate[0] = rate76;
+			_rate[1] = rate77;
+			_rate[2] = rate78;
+			_rate[3] = rate79;
+			_rate[4] = rate80;
+			_rate[5] = rate81;
+			_rate[6] = rate82;
+			_rate[7] = rate83;
+			_rate[8] = rate84;
+			_rate[9] = rate85;
+		}
+		
+		/**
+		 * @return Returns the level.
+		 */
+		public int getLevel()
+		{
+			return _level;
+		}
+		
+		/**
+		 * @return Returns the spCost.
+		 */
+		public int getSpCost()
+		{
+			return _spCost;
+		}
+		public int getExpCost()
+		{
+			return _expCost;
+		}
+		public int getAdenaCost()
+		{
+			return _adenaCost;
+		}
+		
+		public byte getRate(L2PcInstance ply)
+		{
+			if (ply.getLevel() < 76)
+				return 0;
+			return _rate[ply.getLevel() - 76];
+		}
+	}
+}

+ 98 - 179
L2_GameServer/java/com/l2jserver/gameserver/model/L2EnchantSkillLearn.java

@@ -14,195 +14,114 @@
  */
  */
 package com.l2jserver.gameserver.model;
 package com.l2jserver.gameserver.model;
 
 
-import java.util.List;
+import gnu.trove.TIntIntHashMap;
 
 
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
-import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-
-import javolution.util.FastTable;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
 
 
 /**
 /**
  * This class ...
  * This class ...
  *
  *
  * @version $Revision: 1.2.4.2 $ $Date: 2005/03/27 15:29:33 $
  * @version $Revision: 1.2.4.2 $ $Date: 2005/03/27 15:29:33 $
  */
  */
-@SuppressWarnings("unchecked")
 public final class L2EnchantSkillLearn
 public final class L2EnchantSkillLearn
 {
 {
-    private final int _id;
-    private final int _baseLvl;
-    
-    private List<EnchantSkillDetail>[] _enchantDetails = new List[0];
-
-    public L2EnchantSkillLearn(int id, int baseLvl)
-    {
-        _id = id;
-        _baseLvl = baseLvl;
-    }
-
-    /**
-     * @return Returns the id.
-     */
-    public int getId()
-    {
-        return _id;
-    }
-
-    /**
-     * @return Returns the minLevel.
-     */
-    public int getBaseLevel()
-    {
-        return _baseLvl;
-    }
-    
-    public void addEnchantDetail(EnchantSkillDetail esd)
-    {
-        int enchantType = L2EnchantSkillLearn.getEnchantType(esd.getLevel());
-        
-        if (enchantType < 0)
-        {
-            throw new IllegalArgumentException("Skill enchantments should have level higher then 100");
-        }
-        else
-        {
-            if (enchantType >= _enchantDetails.length)
-            {
-                List<EnchantSkillDetail>[] newArray = new List[enchantType+1];
-                System.arraycopy(_enchantDetails, 0, newArray, 0, _enchantDetails.length);
-                _enchantDetails = newArray;
-                _enchantDetails[enchantType] = new FastTable<EnchantSkillDetail>();
-            }
-            int index = L2EnchantSkillLearn.getEnchantIndex(esd.getLevel());
-            _enchantDetails[enchantType].add(index, esd);
-        }
-    }
-    
-    public List<EnchantSkillDetail>[] getEnchantRoutes()
-    {
-        return _enchantDetails;
-    }
-    
-    public EnchantSkillDetail getEnchantSkillDetail(int level)
-    {
-        int enchantType = L2EnchantSkillLearn.getEnchantType(level);
-        if (enchantType < 0 || enchantType >= _enchantDetails.length)
-        {
-            return null;
-        }
-        int index = L2EnchantSkillLearn.getEnchantIndex(level);
-        if (index < 0 || index >= _enchantDetails[enchantType].size())
-        {
-            return null;
-        }
-        return _enchantDetails[enchantType].get(index);
-    }
-    
-    public static int getEnchantIndex(int level)
-    {
-        return (level % 100) - 1;
-    }
-    
-    public static int getEnchantType(int level)
-    {
-        return ((level - 1) / 100) - 1;
-    }
-    
-    public static class EnchantSkillDetail
-    {
-        private final int _level;
-        private final int _spCost;
-        private final int _minSkillLevel;
-        private final int _exp;
-        private final byte _rate76,_rate77,_rate78,_rate79,_rate80,_rate81,_rate82,_rate83,_rate84,_rate85;
+	private final int _id;
+	private final int _baseLvl;
+	private final TIntIntHashMap _enchantRoutes = new TIntIntHashMap();
 
 
-        
-        public EnchantSkillDetail(int lvl, int minSkillLvl, int cost, int exp, byte rate76, byte rate77, byte rate78, byte rate79, byte rate80, byte rate81, byte rate82, byte rate83, byte rate84, byte rate85)
-        {
-            _level = lvl;
-            _minSkillLevel = minSkillLvl;
-            _spCost = cost;
-            _exp = exp;
-            _rate76 = rate76;
-            _rate77 = rate77;
-            _rate78 = rate78;
-            _rate79 = rate79;
-            _rate80 = rate80;
-            _rate81 = rate81;
-            _rate82 = rate82;
-            _rate83 = rate83;
-            _rate84 = rate84;
-            _rate85 = rate85;
-        }
-        
-        /**
-         * @return Returns the level.
-         */
-        public int getLevel()
-        {
-            return _level;
-        }
-        
-        /**
-         * @return Returns the minSkillLevel.
-         */
-        public int getMinSkillLevel()
-        {
-            return _minSkillLevel;
-        }
+	public L2EnchantSkillLearn(int id, int baseLvl)
+	{
+		_id = id;
+		_baseLvl = baseLvl;
+	}
 
 
-        /**
-         * @return Returns the spCost.
-         */
-        public int getSpCost()
-        {
-            return _spCost;
-        }
-        public int getAdena()
-        {
-            return _exp / SkillTreeTable.ADENA_XP_DIV;
-        }
+	public void addNewEnchantRoute(int route, int group)
+	{
+		_enchantRoutes.put(route, group);
+	}
+	/**
+	 * @return Returns the id.
+	 */
+	public int getId()
+	{
+		return _id;
+	}
 
 
-        public byte getRate(L2PcInstance ply)
-        {
-            byte result;
-            switch (ply.getLevel())
-            {
-                case 76:
-                    result = _rate76;
-                    break;
-                case 77:
-                    result = _rate77;
-                    break;
-                case 78:
-                    result = _rate78;
-                    break;
-                case 79:
-                    result = _rate79;
-                    break;
-                case 80:
-                    result = _rate80;
-                    break;
-                case 81:
-                    result = _rate81;
-                    break;
-                case 82:
-                    result = _rate82;
-                    break;
-                case 83:
-                    result = _rate83;
-                    break;
-                case 84:
-                    result = _rate84;
-                    break;
-                case 85:
-                    result = _rate85;
-                    break;
-                default:
-                    result = _rate85;
-                break;
-            }
-            return result;
-        }
-    }
+	/**
+	 * @return Returns the minLevel.
+	 */
+	public int getBaseLevel()
+	{
+		return _baseLvl;
+	}
+	
+	public static int getEnchantRoute(int level)
+	{
+		return (int) Math.floor(level / 100);
+	}
+	
+	public static int getEnchantIndex(int level)
+	{
+		return (level % 100) - 1;
+	}
+	
+	public static int getEnchantType(int level)
+	{
+		return ((level - 1) / 100) - 1;
+	}
+	
+	public L2EnchantSkillGroup getFirstRouteGroup()
+	{
+		return EnchantGroupsTable.getInstance().getEnchantSkillGroupById(_enchantRoutes.getValues()[0]);
+	}
+	
+	public int[] getAllRoutes()
+	{
+		return _enchantRoutes.keys();
+	}
+	
+	public int getMinSkillLevel(int level)
+	{
+		if (level % 100 == 1)
+			return _baseLvl;
+		return level - 1;
+	}
+	
+	public boolean isMaxEnchant(int level)
+	{
+		int enchantType = L2EnchantSkillLearn.getEnchantRoute(level);
+		if (enchantType < 1 || !_enchantRoutes.contains(enchantType))
+		{
+			return false;
+		}
+		int index = L2EnchantSkillLearn.getEnchantIndex(level);
+		
+		if ((index + 1) >= EnchantGroupsTable.getInstance().getEnchantSkillGroupById(_enchantRoutes.get(enchantType)).getEnchantGroupDetails().size())
+		{
+			return true;
+		}
+		return false;
+	}
+	
+	public EnchantSkillDetail getEnchantSkillDetail(int level)
+	{
+		int enchantType = L2EnchantSkillLearn.getEnchantRoute(level);
+		if (enchantType < 1 || !_enchantRoutes.contains(enchantType))
+		{
+			return null;
+		}
+		int index = L2EnchantSkillLearn.getEnchantIndex(level);
+		L2EnchantSkillGroup group = EnchantGroupsTable.getInstance().getEnchantSkillGroupById(_enchantRoutes.get(enchantType));
+		
+		if (index < 0)
+		{
+			return group.getEnchantGroupDetails().get(0);
+		}
+		else if (index >= group.getEnchantGroupDetails().size())
+		{
+			return group.getEnchantGroupDetails().get(EnchantGroupsTable.getInstance().getEnchantSkillGroupById(_enchantRoutes.get(enchantType)).getEnchantGroupDetails().size() - 1);
+		}
+		return group.getEnchantGroupDetails().get(index);
+	}
 }
 }

+ 2 - 1
L2_GameServer/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -61,6 +61,7 @@ import com.l2jserver.gameserver.datatables.AdminCommandAccessRights;
 import com.l2jserver.gameserver.datatables.CharNameTable;
 import com.l2jserver.gameserver.datatables.CharNameTable;
 import com.l2jserver.gameserver.datatables.CharTemplateTable;
 import com.l2jserver.gameserver.datatables.CharTemplateTable;
 import com.l2jserver.gameserver.datatables.ClanTable;
 import com.l2jserver.gameserver.datatables.ClanTable;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.FishTable;
 import com.l2jserver.gameserver.datatables.FishTable;
 import com.l2jserver.gameserver.datatables.HennaTable;
 import com.l2jserver.gameserver.datatables.HennaTable;
 import com.l2jserver.gameserver.datatables.HeroSkillTable;
 import com.l2jserver.gameserver.datatables.HeroSkillTable;
@@ -10418,7 +10419,7 @@ public final class L2PcInstance extends L2Playable
 				boolean isEnchantable = skillMaxLevel > 100;
 				boolean isEnchantable = skillMaxLevel > 100;
 				if (isEnchantable)
 				if (isEnchantable)
 				{
 				{
-					L2EnchantSkillLearn esl = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(s.getId());
+					L2EnchantSkillLearn esl = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(s.getId());
 					if (esl != null)
 					if (esl != null)
 					{
 					{
 						//if player dont have min level to enchant 
 						//if player dont have min level to enchant 

+ 7 - 7
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkill.java

@@ -19,13 +19,13 @@ import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
 import com.l2jserver.Config;
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2Skill;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn.EnchantSkillDetail;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
@@ -97,22 +97,22 @@ public final class RequestExEnchantSkill extends L2GameClientPacket
             return;
             return;
         }
         }
         
         
-        int costMultiplier = SkillTreeTable.NORMAL_ENCHANT_COST_MULTIPLIER;
-        int reqItemId = SkillTreeTable.NORMAL_ENCHANT_BOOK;
+        int costMultiplier = EnchantGroupsTable.NORMAL_ENCHANT_COST_MULTIPLIER;
+        int reqItemId = EnchantGroupsTable.NORMAL_ENCHANT_BOOK;
         
         
-        L2EnchantSkillLearn s = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
+        L2EnchantSkillLearn s = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
         if (s == null)
         if (s == null)
         {
         {
             return;
             return;
         }
         }
         EnchantSkillDetail esd = s.getEnchantSkillDetail(_skillLvl);
         EnchantSkillDetail esd = s.getEnchantSkillDetail(_skillLvl);
-        if (player.getSkillLevel(_skillId) != esd.getMinSkillLevel())
+        if (player.getSkillLevel(_skillId) != s.getMinSkillLevel(_skillLvl))
         {
         {
             return;
             return;
         }
         }
         
         
         int requiredSp = esd.getSpCost() * costMultiplier;
         int requiredSp = esd.getSpCost() * costMultiplier;
-        int requireditems = (esd.getAdena() * costMultiplier);
+        int requireditems = (esd.getAdenaCost() * costMultiplier);
         int rate = esd.getRate(player);
         int rate = esd.getRate(player);
         
         
         if (player.getSp() >= requiredSp)
         if (player.getSp() >= requiredSp)

+ 2 - 2
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillInfo.java

@@ -14,8 +14,8 @@
  */
  */
 package com.l2jserver.gameserver.network.clientpackets;
 package com.l2jserver.gameserver.network.clientpackets;
 
 
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.serverpackets.ExEnchantSkillInfo;
 import com.l2jserver.gameserver.network.serverpackets.ExEnchantSkillInfo;
@@ -71,7 +71,7 @@ public final class RequestExEnchantSkillInfo extends L2GameClientPacket
             return;
             return;
         }
         }
 
 
-        if ( SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(_skillId) == null)
+        if ( EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(_skillId) == null)
         	return;
         	return;
         
         
         int playerSkillLvl = activeChar.getSkillLevel(_skillId);
         int playerSkillLvl = activeChar.getSkillLevel(_skillId);

+ 2 - 2
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillInfoDetail.java

@@ -16,7 +16,7 @@ package com.l2jserver.gameserver.network.clientpackets;
 
 
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.serverpackets.ExEnchantSkillInfoDetail;
 import com.l2jserver.gameserver.network.serverpackets.ExEnchantSkillInfoDetail;
@@ -75,7 +75,7 @@ public final class RequestExEnchantSkillInfoDetail extends L2GameClientPacket
 		// if reqlvl is 100,200,.. check base skill lvl enchant
 		// if reqlvl is 100,200,.. check base skill lvl enchant
 		if ((reqSkillLvl % 100) == 0)
 		if ((reqSkillLvl % 100) == 0)
 		{
 		{
-			L2EnchantSkillLearn esl = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
+			L2EnchantSkillLearn esl = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
 			if (esl != null)
 			if (esl != null)
 			{
 			{
 				// if player dont have min level to enchant
 				// if player dont have min level to enchant

+ 5 - 5
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillRouteChange.java

@@ -19,13 +19,13 @@ import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
 import com.l2jserver.Config;
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2Skill;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn.EnchantSkillDetail;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
@@ -95,9 +95,9 @@ public final class RequestExEnchantSkillRouteChange extends L2GameClientPacket
 			return;
 			return;
 		}
 		}
 
 
-		int reqItemId = SkillTreeTable.CHANGE_ENCHANT_BOOK;
+		int reqItemId = EnchantGroupsTable.CHANGE_ENCHANT_BOOK;
 
 
-		L2EnchantSkillLearn s = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
+		L2EnchantSkillLearn s = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
 		if (s == null)
 		if (s == null)
 		{
 		{
 			return;
 			return;
@@ -119,7 +119,7 @@ public final class RequestExEnchantSkillRouteChange extends L2GameClientPacket
 		EnchantSkillDetail esd = s.getEnchantSkillDetail(_skillLvl);
 		EnchantSkillDetail esd = s.getEnchantSkillDetail(_skillLvl);
 
 
 		int requiredSp = esd.getSpCost();
 		int requiredSp = esd.getSpCost();
-		int requireditems = esd.getAdena();
+		int requireditems = esd.getAdenaCost();
 
 
 		if (player.getSp() >= requiredSp)
 		if (player.getSp() >= requiredSp)
 		{
 		{

+ 7 - 7
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillSafe.java

@@ -19,13 +19,13 @@ import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
 import com.l2jserver.Config;
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2Skill;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn.EnchantSkillDetail;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
@@ -95,22 +95,22 @@ public final class RequestExEnchantSkillSafe extends L2GameClientPacket
 			return;
 			return;
 		}
 		}
 
 
-		int costMultiplier = SkillTreeTable.SAFE_ENCHANT_COST_MULTIPLIER;
-		int reqItemId = SkillTreeTable.SAFE_ENCHANT_BOOK;
+		int costMultiplier = EnchantGroupsTable.SAFE_ENCHANT_COST_MULTIPLIER;
+		int reqItemId = EnchantGroupsTable.SAFE_ENCHANT_BOOK;
 
 
-		L2EnchantSkillLearn s = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
+		L2EnchantSkillLearn s = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
 		if (s == null)
 		if (s == null)
 		{
 		{
 			return;
 			return;
 		}
 		}
 		EnchantSkillDetail esd = s.getEnchantSkillDetail(_skillLvl);
 		EnchantSkillDetail esd = s.getEnchantSkillDetail(_skillLvl);
-		if (player.getSkillLevel(_skillId) != esd.getMinSkillLevel())
+		if (player.getSkillLevel(_skillId) != s.getMinSkillLevel(_skillLvl))
 		{
 		{
 			return;
 			return;
 		}
 		}
 
 
 		int requiredSp = esd.getSpCost() * costMultiplier;
 		int requiredSp = esd.getSpCost() * costMultiplier;
-		int requireditems = esd.getAdena() * costMultiplier;
+		int requireditems = esd.getAdenaCost() * costMultiplier;
 		int rate = esd.getRate(player);
 		int rate = esd.getRate(player);
 
 
 		if (player.getSp() >= requiredSp)
 		if (player.getSp() >= requiredSp)

+ 5 - 5
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/RequestExEnchantSkillUntrain.java

@@ -19,13 +19,13 @@ import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
 import com.l2jserver.Config;
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.datatables.SkillTable;
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ItemInstance;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2ShortCut;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2Skill;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn.EnchantSkillDetail;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
 import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
@@ -89,7 +89,7 @@ public final class RequestExEnchantSkillUntrain extends L2GameClientPacket
         	return;
         	return;
         }
         }
 
 
-		L2EnchantSkillLearn s = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
+		L2EnchantSkillLearn s = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(_skillId);
 		if (s == null)
 		if (s == null)
 			return;
 			return;
 		
 		
@@ -102,7 +102,7 @@ public final class RequestExEnchantSkillUntrain extends L2GameClientPacket
 		if (skill == null)
 		if (skill == null)
 			return;
 			return;
 		
 		
-		int reqItemId = SkillTreeTable.UNTRAIN_ENCHANT_BOOK;
+		int reqItemId = EnchantGroupsTable.UNTRAIN_ENCHANT_BOOK;
 		
 		
 		int currentLevel = player.getSkillLevel(_skillId);
 		int currentLevel = player.getSkillLevel(_skillId);
 		if (currentLevel - 1 != _skillLvl && (currentLevel % 100 != 1 || _skillLvl != s.getBaseLevel()))
 		if (currentLevel - 1 != _skillLvl && (currentLevel % 100 != 1 || _skillLvl != s.getBaseLevel()))
@@ -111,7 +111,7 @@ public final class RequestExEnchantSkillUntrain extends L2GameClientPacket
 		EnchantSkillDetail esd = s.getEnchantSkillDetail(currentLevel);
 		EnchantSkillDetail esd = s.getEnchantSkillDetail(currentLevel);
 		
 		
 		int requiredSp = esd.getSpCost();
 		int requiredSp = esd.getSpCost();
-		int requireditems = esd.getAdena();
+		int requireditems = esd.getAdenaCost();
 		
 		
 		L2ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
 		L2ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
 		if (Config.ES_SP_BOOK_NEEDED)
 		if (Config.ES_SP_BOOK_NEEDED)

+ 11 - 19
L2_GameServer/java/com/l2jserver/gameserver/network/serverpackets/ExEnchantSkillInfo.java

@@ -14,11 +14,9 @@
  */
  */
 package com.l2jserver.gameserver.network.serverpackets;
 package com.l2jserver.gameserver.network.serverpackets;
 
 
-import java.util.List;
-
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn.EnchantSkillDetail;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
 
 
 import javolution.util.FastList;
 import javolution.util.FastList;
 
 
@@ -37,16 +35,14 @@ public final class ExEnchantSkillInfo extends L2GameServerPacket
 		_id = id;
 		_id = id;
 		_lvl = lvl;
 		_lvl = lvl;
 
 
-		L2EnchantSkillLearn enchantLearn = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(_id);
+		L2EnchantSkillLearn enchantLearn = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(_id);
 		// do we have this skill?
 		// do we have this skill?
 		if (enchantLearn != null)
 		if (enchantLearn != null)
 		{
 		{
 			// skill already enchanted?
 			// skill already enchanted?
 			if (_lvl > 100)
 			if (_lvl > 100)
 			{
 			{
-				int route = (_lvl / 100) -1;
-				if (_lvl % 100 >= enchantLearn.getEnchantRoutes()[route].size())
-					_maxEnchanted = true;
+				_maxEnchanted = enchantLearn.isMaxEnchant(_lvl);
 				
 				
 				// get detail for next level
 				// get detail for next level
 				EnchantSkillDetail esd = enchantLearn.getEnchantSkillDetail(_lvl);
 				EnchantSkillDetail esd = enchantLearn.getEnchantSkillDetail(_lvl);
@@ -54,32 +50,28 @@ public final class ExEnchantSkillInfo extends L2GameServerPacket
 				// if it exists add it
 				// if it exists add it
 				if (esd != null)
 				if (esd != null)
 				{
 				{
-					_routes.add(esd.getLevel()); // current enchant add firts
+					_routes.add(_lvl); // current enchant add firts
 				}
 				}
 
 
-				int diff = (_lvl % 100) - 1; // indexed form 0
+				int skillLvL = (_lvl % 100);
 
 
-				for (List<EnchantSkillDetail> esd1 : enchantLearn.getEnchantRoutes())
+				for (int route : enchantLearn.getAllRoutes())
 				{
 				{
-					if (esd1 == null)
-						continue;
-					if (esd1.get(0).getLevel() == _lvl) // skip current
+					if ((route * 100 + skillLvL) == _lvl) // skip current
 						continue;
 						continue;
 					// add other levels of all routes - same lvl as enchanted
 					// add other levels of all routes - same lvl as enchanted
 					// lvl
 					// lvl
-					_routes.add(esd1.get(diff).getLevel());
+					_routes.add(route * 100 + skillLvL);
 				}
 				}
 
 
 			}
 			}
 			else
 			else
 			// not already enchanted
 			// not already enchanted
 			{
 			{
-				for (List<EnchantSkillDetail> esd : enchantLearn.getEnchantRoutes())
+				for (int route : enchantLearn.getAllRoutes())
 				{
 				{
-					if (esd == null)
-						continue;
 					// add first level (+1) of all routes
 					// add first level (+1) of all routes
-					_routes.add(esd.get(0).getLevel());
+					_routes.add(route * 100 + 1);
 				}
 				}
 			}
 			}
 		}
 		}

+ 12 - 26
L2_GameServer/java/com/l2jserver/gameserver/network/serverpackets/ExEnchantSkillInfoDetail.java

@@ -14,12 +14,10 @@
  */
  */
 package com.l2jserver.gameserver.network.serverpackets;
 package com.l2jserver.gameserver.network.serverpackets;
 
 
-import java.util.List;
-
 import com.l2jserver.Config;
 import com.l2jserver.Config;
-import com.l2jserver.gameserver.datatables.SkillTreeTable;
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
-import com.l2jserver.gameserver.model.L2EnchantSkillLearn.EnchantSkillDetail;
+import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillDetail;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 
 
 /**
 /**
@@ -46,43 +44,31 @@ public class ExEnchantSkillInfoDetail extends L2GameServerPacket
 	public ExEnchantSkillInfoDetail(int type, int skillid, int skilllvl, L2PcInstance ply)
 	public ExEnchantSkillInfoDetail(int type, int skillid, int skilllvl, L2PcInstance ply)
 	{
 	{
 
 
-		L2EnchantSkillLearn enchantLearn = SkillTreeTable.getInstance().getSkillEnchantmentBySkillId(skillid);
+		L2EnchantSkillLearn enchantLearn = EnchantGroupsTable.getInstance().getSkillEnchantmentBySkillId(skillid);
 		EnchantSkillDetail esd = null;
 		EnchantSkillDetail esd = null;
 		// do we have this skill?
 		// do we have this skill?
 		if (enchantLearn != null)
 		if (enchantLearn != null)
 		{
 		{
 			if (skilllvl > 100)
 			if (skilllvl > 100)
 			{
 			{
-				int route = (skilllvl / 100) -1;
-				if (skilllvl % 100 == 0)
-					esd = enchantLearn.getEnchantRoutes()[route].get(0);
-				else if (skilllvl % 100 >= enchantLearn.getEnchantRoutes()[route].size())
-					esd = enchantLearn.getEnchantRoutes()[route].get(enchantLearn.getEnchantRoutes()[route].size()-1);
-				else
-					esd = enchantLearn.getEnchantSkillDetail(skilllvl);
+				esd = enchantLearn.getEnchantSkillDetail(skilllvl);
 			}
 			}
 			else
 			else
-				//find first enchant route
-				for (List<EnchantSkillDetail> list : enchantLearn.getEnchantRoutes())
-					if (list != null)
-					{
-						esd = list.get(0);
-						break;
-					}
+				esd = enchantLearn.getFirstRouteGroup().getEnchantGroupDetails().get(0);
 		}
 		}
 
 
 		if (esd == null)
 		if (esd == null)
 			throw new IllegalArgumentException("Skill "+skillid + " dont have enchant data for level "+skilllvl);
 			throw new IllegalArgumentException("Skill "+skillid + " dont have enchant data for level "+skilllvl);
 
 
 		if (type == 0)
 		if (type == 0)
-			multi = SkillTreeTable.NORMAL_ENCHANT_COST_MULTIPLIER;
+			multi = EnchantGroupsTable.NORMAL_ENCHANT_COST_MULTIPLIER;
 		else if (type == 1)
 		else if (type == 1)
-			multi = SkillTreeTable.SAFE_ENCHANT_COST_MULTIPLIER;
+			multi = EnchantGroupsTable.SAFE_ENCHANT_COST_MULTIPLIER;
 		_chance = esd.getRate(ply);
 		_chance = esd.getRate(ply);
 		_sp = esd.getSpCost();
 		_sp = esd.getSpCost();
 		if (type == TYPE_UNTRAIN_ENCHANT)
 		if (type == TYPE_UNTRAIN_ENCHANT)
 			_sp = (int) (0.8 * _sp);
 			_sp = (int) (0.8 * _sp);
-		_adenacount = esd.getAdena() * multi;
+		_adenacount = esd.getAdenaCost() * multi;
 		_type = type;
 		_type = type;
 		_skillid = skillid;
 		_skillid = skillid;
 		_skilllvl = skilllvl;
 		_skilllvl = skilllvl;
@@ -90,19 +76,19 @@ public class ExEnchantSkillInfoDetail extends L2GameServerPacket
 		switch (type)
 		switch (type)
 		{
 		{
 		case TYPE_NORMAL_ENCHANT:
 		case TYPE_NORMAL_ENCHANT:
-			bookId = SkillTreeTable.NORMAL_ENCHANT_BOOK;
+			bookId = EnchantGroupsTable.NORMAL_ENCHANT_BOOK;
 			reqCount = ((_skilllvl % 100 > 1) ? 0 : 1) ;
 			reqCount = ((_skilllvl % 100 > 1) ? 0 : 1) ;
 			break;
 			break;
 		case TYPE_SAFE_ENCHANT:
 		case TYPE_SAFE_ENCHANT:
-			bookId = SkillTreeTable.SAFE_ENCHANT_BOOK;
+			bookId = EnchantGroupsTable.SAFE_ENCHANT_BOOK;
 			reqCount = 1;
 			reqCount = 1;
 			break;
 			break;
 		case TYPE_UNTRAIN_ENCHANT:
 		case TYPE_UNTRAIN_ENCHANT:
-			bookId = SkillTreeTable.UNTRAIN_ENCHANT_BOOK;
+			bookId = EnchantGroupsTable.UNTRAIN_ENCHANT_BOOK;
 			reqCount = 1;
 			reqCount = 1;
 			break;
 			break;
 		case TYPE_CHANGE_ENCHANT:
 		case TYPE_CHANGE_ENCHANT:
-			bookId = SkillTreeTable.CHANGE_ENCHANT_BOOK;
+			bookId = EnchantGroupsTable.CHANGE_ENCHANT_BOOK;
 			reqCount = 1;
 			reqCount = 1;
 			break;
 			break;
 		default:
 		default:

+ 17 - 16
L2_GameServer/java/com/l2jserver/gameserver/skills/DocumentSkill.java

@@ -24,6 +24,7 @@ import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.Node;
 
 
+import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.skills.conditions.Condition;
 import com.l2jserver.gameserver.skills.conditions.Condition;
 import com.l2jserver.gameserver.templates.StatsSet;
 import com.l2jserver.gameserver.templates.StatsSet;
@@ -149,22 +150,22 @@ class DocumentSkill extends DocumentBase {
 		String skillName = attrs.getNamedItem("name").getNodeValue();
 		String skillName = attrs.getNamedItem("name").getNodeValue();
 		String levels = attrs.getNamedItem("levels").getNodeValue();
 		String levels = attrs.getNamedItem("levels").getNodeValue();
 		int lastLvl = Integer.parseInt(levels);
 		int lastLvl = Integer.parseInt(levels);
-        if (attrs.getNamedItem("enchantLevels1") != null)
-            enchantLevels1 = Integer.parseInt(attrs.getNamedItem("enchantLevels1").getNodeValue());
-        if (attrs.getNamedItem("enchantLevels2") != null)
-            enchantLevels2 = Integer.parseInt(attrs.getNamedItem("enchantLevels2").getNodeValue());
-        if (attrs.getNamedItem("enchantLevels3") != null)
-            enchantLevels3 = Integer.parseInt(attrs.getNamedItem("enchantLevels3").getNodeValue());
-        if (attrs.getNamedItem("enchantLevels4") != null)
-            enchantLevels4 = Integer.parseInt(attrs.getNamedItem("enchantLevels4").getNodeValue());
-        if (attrs.getNamedItem("enchantLevels5") != null)
-            enchantLevels5 = Integer.parseInt(attrs.getNamedItem("enchantLevels5").getNodeValue());
-        if (attrs.getNamedItem("enchantLevels6") != null)
-            enchantLevels6 = Integer.parseInt(attrs.getNamedItem("enchantLevels6").getNodeValue());
-        if (attrs.getNamedItem("enchantLevels7") != null)
-            enchantLevels7 = Integer.parseInt(attrs.getNamedItem("enchantLevels7").getNodeValue());
-        if (attrs.getNamedItem("enchantLevels8") != null)
-            enchantLevels8 = Integer.parseInt(attrs.getNamedItem("enchantLevels8").getNodeValue());
+        if (attrs.getNamedItem("enchantGroup1") != null)
+            enchantLevels1 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 1, Integer.parseInt(attrs.getNamedItem("enchantGroup1").getNodeValue()));
+        if (attrs.getNamedItem("enchantGroup2") != null)
+        	enchantLevels2 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 2, Integer.parseInt(attrs.getNamedItem("enchantGroup2").getNodeValue()));
+        if (attrs.getNamedItem("enchantGroup3") != null)
+        	enchantLevels3 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 3, Integer.parseInt(attrs.getNamedItem("enchantGroup3").getNodeValue()));
+        if (attrs.getNamedItem("enchantGroup4") != null)
+        	enchantLevels4 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 4, Integer.parseInt(attrs.getNamedItem("enchantGroup4").getNodeValue()));
+        if (attrs.getNamedItem("enchantGroup5") != null)
+        	enchantLevels5 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 5, Integer.parseInt(attrs.getNamedItem("enchantGroup5").getNodeValue()));
+        if (attrs.getNamedItem("enchantGroup6") != null)
+        	enchantLevels6 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 6, Integer.parseInt(attrs.getNamedItem("enchantGroup6").getNodeValue()));
+        if (attrs.getNamedItem("enchantGroup7") != null)
+        	enchantLevels7 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 7, Integer.parseInt(attrs.getNamedItem("enchantGroup7").getNodeValue()));
+        if (attrs.getNamedItem("enchantGroup8") != null)
+        	enchantLevels8 = EnchantGroupsTable.getInstance().addNewRouteForSkill(skillId, lastLvl, 8, Integer.parseInt(attrs.getNamedItem("enchantGroup8").getNodeValue()));
 
 
         _currentSkill.id     = skillId;
         _currentSkill.id     = skillId;
         _currentSkill.name   = skillName;
         _currentSkill.name   = skillName;