Bläddra i källkod

BETA: Unhardcoded Experience Table and Moved to DP XML (data/stats/experience.xml)
It's now possible to change the starting subclass level by changing BaseSubclassLevel in characters.properties
It's now possible to setup datapack root also for loginserver by changing DatapackRoot in loginserver.properties
EmailSystem should be disabled by default

mrTJO 14 år sedan
förälder
incheckning
6bb7a61af7
22 ändrade filer med 198 tillägg och 177 borttagningar
  1. 4 0
      L2J_Server_BETA/java/com/l2jserver/Config.java
  2. 3 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/GameServer.java
  3. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/SevenSignsFestival.java
  4. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/communitybbs/Manager/RegionBBSManager.java
  5. 4 5
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CharSummonTable.java
  6. 124 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/ExperienceTable.java
  7. 5 5
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Summon.java
  8. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
  9. 5 5
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/stat/PcStat.java
  10. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/stat/PetStat.java
  11. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/stat/PlayableStat.java
  12. 0 124
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/base/Experience.java
  13. 11 10
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/base/SubClass.java
  14. 3 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/CharSelectionInfo.java
  15. 3 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/GMViewCharacterInfo.java
  16. 3 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/UserInfo.java
  17. 7 5
      L2J_Server_BETA/java/com/l2jserver/gameserver/skills/l2skills/L2SkillSummon.java
  18. 3 1
      L2J_Server_BETA/java/com/l2jserver/loginserver/GameServerTable.java
  19. 2 2
      L2J_Server_BETA/java/com/l2jserver/loginserver/mail/MailSystem.java
  20. 4 0
      L2J_Server_BETA/java/config/Character.properties
  21. 1 1
      L2J_Server_BETA/java/config/email.properties
  22. 4 0
      L2J_Server_BETA/java/config/loginserver.properties

+ 4 - 0
L2J_Server_BETA/java/com/l2jserver/Config.java

@@ -144,6 +144,7 @@ public final class Config
 	public static int MIN_DEBUFF_CHANCE;
 	public static int MAX_DEBUFF_CHANCE;
 	public static byte MAX_SUBCLASS;
+	public static byte BASE_SUBCLASS_LEVEL;
 	public static byte MAX_SUBCLASS_LEVEL;
 	public static int MAX_PVTSTORESELL_SLOTS_DWARF;
 	public static int MAX_PVTSTORESELL_SLOTS_OTHER;
@@ -1571,6 +1572,7 @@ public final class Config
 					MIN_DEBUFF_CHANCE = Integer.parseInt(Character.getProperty("MinDebuffChance", "10"));
 					MAX_DEBUFF_CHANCE = Integer.parseInt(Character.getProperty("MaxDebuffChance", "90"));
 					MAX_SUBCLASS = Byte.parseByte(Character.getProperty("MaxSubclass", "3"));
+					BASE_SUBCLASS_LEVEL = Byte.parseByte(Character.getProperty("BaseSubclassLevel", "40"));
 					MAX_SUBCLASS_LEVEL = Byte.parseByte(Character.getProperty("MaxSubclassLevel", "80"));
 					MAX_PVTSTORESELL_SLOTS_DWARF = Integer.parseInt(Character.getProperty("MaxPvtStoreSellSlotsDwarf", "4"));
 					MAX_PVTSTORESELL_SLOTS_OTHER = Integer.parseInt(Character.getProperty("MaxPvtStoreSellSlotsOther", "3"));
@@ -2855,6 +2857,8 @@ public final class Config
 					LOGIN_BIND_ADDRESS = serverSettings.getProperty("LoginserverHostname", "*");
 					PORT_LOGIN = Integer.parseInt(serverSettings.getProperty("LoginserverPort", "2106"));
 					
+					DATAPACK_ROOT = new File(serverSettings.getProperty("DatapackRoot", ".")).getCanonicalFile();
+					
 					DEBUG = Boolean.parseBoolean(serverSettings.getProperty("Debug", "false"));
 					
 					ACCEPT_NEW_GAMESERVER = Boolean.parseBoolean(serverSettings.getProperty("AcceptNewGameServer","True"));

+ 3 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/GameServer.java

@@ -47,6 +47,7 @@ import com.l2jserver.gameserver.datatables.DoorTable;
 import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
 import com.l2jserver.gameserver.datatables.EnchantHPBonusData;
 import com.l2jserver.gameserver.datatables.EventDroplist;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.FishTable;
 import com.l2jserver.gameserver.datatables.GMSkillTable;
 import com.l2jserver.gameserver.datatables.HelperBuffTable;
@@ -236,6 +237,7 @@ public class GameServer
 		FishTable.getInstance();
 		
 		printSection("Characters");
+		ExperienceTable.getInstance();
 		CharTemplateTable.getInstance();
 		CharNameTable.getInstance();
 		LevelUpData.getInstance();
@@ -312,7 +314,7 @@ public class GameServer
 		try
 		{
 			_log.info("Loading Server Scripts");
-			File scripts = new File(Config.DATAPACK_ROOT + "/data/scripts.cfg");
+			File scripts = new File(Config.DATAPACK_ROOT, "data/scripts.cfg");
 			if(!Config.ALT_DEV_NO_HANDLERS || !Config.ALT_DEV_NO_QUESTS)
 				L2ScriptEngineManager.getInstance().executeScriptList(scripts);
 		}

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/SevenSignsFestival.java

@@ -34,6 +34,7 @@ import com.l2jserver.L2DatabaseFactory;
 import com.l2jserver.gameserver.ai.CtrlIntention;
 import com.l2jserver.gameserver.datatables.CharNameTable;
 import com.l2jserver.gameserver.datatables.ClanTable;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.MapRegionTable;
 import com.l2jserver.gameserver.datatables.NpcTable;
 import com.l2jserver.gameserver.datatables.SpawnTable;
@@ -47,7 +48,6 @@ import com.l2jserver.gameserver.model.SpawnListener;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2FestivalMonsterInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
@@ -848,7 +848,7 @@ public class SevenSignsFestival implements SpawnListener
 	 */
 	public static final int getMaxLevelForFestival(int festivalId)
 	{
-		int maxLevel = (Experience.MAX_LEVEL - 1);
+		int maxLevel = (ExperienceTable.getInstance().getMaxLevel() - 1);
 		
 		switch (festivalId)
 		{

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/communitybbs/Manager/RegionBBSManager.java

@@ -26,10 +26,10 @@ import javolution.util.FastMap;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.GameServer;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.model.BlockList;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
@@ -131,9 +131,9 @@ public class RegionBBSManager extends BaseBBSManager
 			{
 				long nextLevelExp = 0;
 				long nextLevelExpNeeded = 0;
-				if (player.getLevel() < (Experience.MAX_LEVEL - 1))
+				if (player.getLevel() < (ExperienceTable.getInstance().getMaxLevel() - 1))
 				{
-					nextLevelExp = Experience.LEVEL[player.getLevel() + 1];
+					nextLevelExp = ExperienceTable.getInstance().getExpForLevel(player.getLevel() + 1);
 					nextLevelExpNeeded = nextLevelExp - player.getExp();
 				}
 				

+ 4 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CharSummonTable.java

@@ -33,7 +33,6 @@ import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2SiegeSummonInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2SummonInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.network.serverpackets.PetItemList;
 import com.l2jserver.gameserver.skills.l2skills.L2SkillSummon;
 import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
@@ -214,14 +213,14 @@ public class CharSummonTable
 				summon.setTitle(activeChar.getName());
 				summon.setExpPenalty(skill.getExpPenalty());
 				
-				if (summon.getLevel() >= Experience.PET_MAX_LEVEL)
+				if (summon.getLevel() >= ExperienceTable.getInstance().getMaxPetLevel())
 				{
-					summon.getStat().setExp(Experience.LEVEL[Experience.PET_MAX_LEVEL - 1]);
-					_log.warning("Summon (" + summon.getName() + ") NpcID: " + summon.getNpcId() + " has a level above 86. Please rectify.");
+					summon.getStat().setExp(ExperienceTable.getInstance().getExpForLevel(ExperienceTable.getInstance().getMaxPetLevel()-1));
+					_log.warning("Summon (" + summon.getName() + ") NpcID: " + summon.getNpcId() + " has a level above "+ExperienceTable.getInstance().getMaxPetLevel()+". Please rectify.");
 				}
 				else
 				{
-					summon.getStat().setExp(Experience.LEVEL[(summon.getLevel() % Experience.PET_MAX_LEVEL)]);
+					summon.getStat().setExp(ExperienceTable.getInstance().getExpForLevel(summon.getLevel() % ExperienceTable.getInstance().getMaxPetLevel()));
 				}
 				summon.setCurrentHp(curHp);
 				summon.setCurrentMp(curMp);

+ 124 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/ExperienceTable.java

@@ -0,0 +1,124 @@
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import com.l2jserver.Config;
+
+/**
+ * @author mrTJO
+ *
+ */
+public class ExperienceTable
+{
+	private static Logger _log = Logger.getLogger(ExperienceTable.class.getName());
+	private byte MAX_LEVEL;
+	private byte MAX_PET_LEVEL;
+	
+	private Map<Integer, Long> _expTable;
+	
+	public static ExperienceTable getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	private ExperienceTable()
+	{
+		loadTable();
+	}
+	
+	private void loadTable()
+	{
+		File xml = new File(Config.DATAPACK_ROOT, "data/experience.xml");
+		Document doc = null;
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		factory.setValidating(false);
+		factory.setIgnoringComments(true);
+		if (xml.exists())
+		{
+			try
+			{
+				doc = factory.newDocumentBuilder().parse(xml);
+			}
+			catch (IOException e)
+			{
+				_log.log(Level.WARNING, "Could not read experience.xml table: " + e.getMessage(), e);
+			}
+			catch (Exception e)
+			{
+				_log.log(Level.WARNING, "Could not parse experience.xml table: " + e.getMessage(), e);
+			}
+			
+			Node table = doc.getFirstChild();
+			NamedNodeMap tableAttr = table.getAttributes();
+			
+			MAX_LEVEL = (byte)(Byte.parseByte(tableAttr.getNamedItem("maxLevel").getNodeValue())+1);
+			MAX_PET_LEVEL = (byte)(Byte.parseByte(tableAttr.getNamedItem("maxPetLevel").getNodeValue())+1);
+
+			_expTable = new HashMap<Integer, Long>(MAX_LEVEL+1);
+			
+			for (Node experience = table.getFirstChild(); experience != null; experience = experience.getNextSibling())
+			{
+				if (experience.getNodeName().equals("experience"))
+				{
+					NamedNodeMap attrs = experience.getAttributes();
+					int level = Integer.parseInt(attrs.getNamedItem("level").getNodeValue());
+					long exp = Long.parseLong(attrs.getNamedItem("tolevel").getNodeValue());
+					
+					_expTable.put(level, exp);
+				}
+			}
+			
+			_log.info("ExperienceTable: Loaded "+_expTable.size()+" levels");
+			_log.info("ExperienceTable: Max Player Level is: "+(MAX_LEVEL-1));
+			_log.info("ExperienceTable: Max Pet Level is: "+(MAX_PET_LEVEL-1));
+		}
+		else
+			_log.warning("ExperienceTable: experience.xml not found!");
+	}
+	
+	public long getExpForLevel(int level)
+	{
+		return _expTable.get(level);
+	}
+	
+	public byte getMaxLevel()
+	{
+		return MAX_LEVEL;
+	}
+	
+	public byte getMaxPetLevel()
+	{
+		return MAX_PET_LEVEL;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ExperienceTable _instance = new ExperienceTable();
+	}
+}

+ 5 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Summon.java

@@ -20,6 +20,7 @@ import com.l2jserver.Config;
 import com.l2jserver.gameserver.ai.CtrlIntention;
 import com.l2jserver.gameserver.ai.L2CharacterAI;
 import com.l2jserver.gameserver.ai.L2SummonAI;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.ItemTable;
 import com.l2jserver.gameserver.instancemanager.TerritoryWarManager;
 import com.l2jserver.gameserver.model.L2ItemInstance;
@@ -38,7 +39,6 @@ import com.l2jserver.gameserver.model.actor.instance.L2SummonInstance;
 import com.l2jserver.gameserver.model.actor.knownlist.SummonKnownList;
 import com.l2jserver.gameserver.model.actor.stat.SummonStat;
 import com.l2jserver.gameserver.model.actor.status.SummonStatus;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.model.itemcontainer.PetInventory;
 import com.l2jserver.gameserver.model.olympiad.OlympiadGameManager;
 import com.l2jserver.gameserver.network.SystemMessageId;
@@ -222,20 +222,20 @@ public abstract class L2Summon extends L2Playable
 	
 	public long getExpForThisLevel()
 	{
-		if(getLevel() >= Experience.LEVEL.length)
+		if(getLevel() >= ExperienceTable.getInstance().getMaxPetLevel())
 		{
 			return 0;
 		}
-		return Experience.LEVEL[getLevel()];
+		return ExperienceTable.getInstance().getExpForLevel(getLevel());
 	}
 	
 	public long getExpForNextLevel()
 	{
-		if(getLevel() >= Experience.LEVEL.length - 1)
+		if(getLevel() >= ExperienceTable.getInstance().getMaxPetLevel() - 1)
 		{
 			return 0;
 		}
-		return Experience.LEVEL[getLevel()+1];
+		return ExperienceTable.getInstance().getExpForLevel(getLevel()+1);
 	}
 	
 	@Override

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -63,6 +63,7 @@ import com.l2jserver.gameserver.datatables.CharSummonTable;
 import com.l2jserver.gameserver.datatables.CharTemplateTable;
 import com.l2jserver.gameserver.datatables.ClanTable;
 import com.l2jserver.gameserver.datatables.EnchantGroupsTable;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.FishTable;
 import com.l2jserver.gameserver.datatables.HennaTable;
 import com.l2jserver.gameserver.datatables.HeroSkillTable;
@@ -145,7 +146,6 @@ import com.l2jserver.gameserver.model.actor.stat.PcStat;
 import com.l2jserver.gameserver.model.actor.status.PcStatus;
 import com.l2jserver.gameserver.model.base.ClassId;
 import com.l2jserver.gameserver.model.base.ClassLevel;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.model.base.PlayerClass;
 import com.l2jserver.gameserver.model.base.Race;
 import com.l2jserver.gameserver.model.base.SubClass;
@@ -5879,10 +5879,10 @@ public final class L2PcInstance extends L2Playable
 		// Calculate the Experience loss
 		long lostExp = 0;
 		if (!L2Event.isParticipant(this))
-			if (lvl < Experience.MAX_LEVEL)
+			if (lvl < ExperienceTable.getInstance().getMaxLevel())
 				lostExp = Math.round((getStat().getExpForLevel(lvl+1) - getStat().getExpForLevel(lvl)) * percentLost /100);
 			else
-				lostExp = Math.round((getStat().getExpForLevel(Experience.MAX_LEVEL) - getStat().getExpForLevel(Experience.MAX_LEVEL - 1)) * percentLost /100);
+				lostExp = Math.round((getStat().getExpForLevel(ExperienceTable.getInstance().getMaxLevel()) - getStat().getExpForLevel(ExperienceTable.getInstance().getMaxLevel() - 1)) * percentLost /100);
 		
 		// Get the Experience before applying penalty
 		setExpBeforeDeath(getExp());

+ 5 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/stat/PcStat.java

@@ -15,12 +15,12 @@
 package com.l2jserver.gameserver.model.actor.stat;
 
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.NpcTable;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2ClassMasterInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.model.entity.RecoBonus;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.network.SystemMessageId;
@@ -216,7 +216,7 @@ public class PcStat extends PlayableStat
 	@Override
 	public final boolean addLevel(byte value)
 	{
-		if (getLevel() + value > Experience.MAX_LEVEL - 1)
+		if (getLevel() + value > ExperienceTable.getInstance().getMaxLevel() - 1)
 			return false;
 		
 		boolean levelIncreased = super.addLevel(value);
@@ -286,7 +286,7 @@ public class PcStat extends PlayableStat
 	@Override
 	public final long getExpForLevel(int level)
 	{
-		return Experience.LEVEL[level];
+		return ExperienceTable.getInstance().getExpForLevel(level);
 	}
 	
 	// =========================================================
@@ -330,8 +330,8 @@ public class PcStat extends PlayableStat
 	@Override
 	public final void setLevel(byte value)
 	{
-		if (value > Experience.MAX_LEVEL - 1)
-			value = Experience.MAX_LEVEL - 1;
+		if (value > ExperienceTable.getInstance().getMaxLevel() - 1)
+			value = (byte)(ExperienceTable.getInstance().getMaxLevel() - 1);
 		
 		if (getActiveChar().isSubClassActive())
 			getActiveChar().getSubClasses().get(getActiveChar().getClassIndex()).setLevel(value);

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/stat/PetStat.java

@@ -14,11 +14,11 @@
  */
 package com.l2jserver.gameserver.model.actor.stat;
 
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.PetDataTable;
 import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
 import com.l2jserver.gameserver.network.serverpackets.StatusUpdate;
@@ -185,6 +185,6 @@ public class PetStat extends SummonStat
 	@Override
 	public int getMaxLevel()
 	{
-		return Experience.PET_MAX_LEVEL;
+		return ExperienceTable.getInstance().getMaxPetLevel();
 	}
 }

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/stat/PlayableStat.java

@@ -17,13 +17,13 @@ package com.l2jserver.gameserver.model.actor.stat;
 import java.util.logging.Logger;
 
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.PetDataTable;
 import com.l2jserver.gameserver.instancemanager.ZoneManager;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Playable;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.model.zone.type.L2SwampZone;
 import com.l2jserver.gameserver.network.communityserver.CommunityServerThread;
 import com.l2jserver.gameserver.network.communityserver.writepackets.WorldInfo;
@@ -204,6 +204,6 @@ public class PlayableStat extends CharStat
 	
 	public int getMaxLevel()
 	{
-		return Experience.MAX_LEVEL;
+		return ExperienceTable.getInstance().getMaxLevel();
 	}
 }

+ 0 - 124
L2J_Server_BETA/java/com/l2jserver/gameserver/model/base/Experience.java

@@ -1,124 +0,0 @@
-/*
- * 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.base;
-
-/**
-
- *
- */
-public class Experience
-{
-	public final static long LEVEL[] =
-	{
-		-1L, // level 0 (unreachable)
-		0L,
-		68L,
-		363L,
-		1168L,
-		2884L,
-		6038L,
-		11287L,
-		19423L,
-		31378L,
-		48229L, //level 10
-		71201L,
-		101676L,
-		141192L,
-		191452L,
-		254327L,
-		331864L,
-		426284L,
-		539995L,
-		675590L,
-		835854L, //level 20
-		1023775L,
-		1242536L,
-		1495531L,
-		1786365L,
-		2118860L,
-		2497059L,
-		2925229L,
-		3407873L,
-		3949727L,
-		4555766L, //level 30
-		5231213L,
-		5981539L,
-		6812472L,
-		7729999L,
-		8740372L,
-		9850111L,
-		11066012L,
-		12395149L,
-		13844879L,
-		15422851L, //level 40
-		17137002L,
-		18995573L,
-		21007103L,
-		23180442L,
-		25524751L,
-		28049509L,
-		30764519L,
-		33679907L,
-		36806133L,
-		40153995L, //level 50
-		45524865L,
-		51262204L,
-		57383682L,
-		63907585L,
-		70852742L,
-		80700339L,
-		91162131L,
-		102265326L,
-		114038008L,
-		126509030L, //level 60
-		146307211L,
-		167243291L,
-		189363788L,
-		212716741L,
-		237351413L,
-		271973532L,
-		308441375L,
-		346825235L,
-		387197529L,
-		429632402L, //level 70
-		474205751L,
-		532692055L,
-		606319094L,
-		696376867L,
-		804219972L,
-		931275828L,
-		1151275834L,
-		1511275834L,
-		2099275834L,
-		4200000000L, //level 80
-		6300000000L, //level 81
-		8820000000L, //level 82
-		11844000000L, //level 83
-		15472800000L, //level 84
-		19827360000L, //level 85
-		25314105600L, //level 86
-		32211728640L  //level 87
-	};
-	
-	/**
-	 * This is the first UNREACHABLE level.<BR>
-	 *   ex: If you want a max at 85 & 100.00%, you have to put 86.<BR><BR>
-	 */
-	public final static byte MAX_LEVEL = 86;
-	public final static byte PET_MAX_LEVEL = 87;
-	
-	public final static byte MIN_NEWBIE_LEVEL = 6;
-	public final static byte MAX_NEWBIE_LEVEL = 39;
-}

+ 11 - 10
L2J_Server_BETA/java/com/l2jserver/gameserver/model/base/SubClass.java

@@ -15,6 +15,7 @@
 package com.l2jserver.gameserver.model.base;
 
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 
 /**
  * Character Sub-Class Definition
@@ -25,12 +26,12 @@ import com.l2jserver.Config;
  */
 public final class SubClass
 {
-	private static final byte _maxLevel = Config.MAX_SUBCLASS_LEVEL < Experience.MAX_LEVEL ? Config.MAX_SUBCLASS_LEVEL : Experience.MAX_LEVEL - 1;
+	private static final byte _maxLevel = Config.MAX_SUBCLASS_LEVEL < ExperienceTable.getInstance().getMaxLevel() ? Config.MAX_SUBCLASS_LEVEL : (byte)(ExperienceTable.getInstance().getMaxLevel() - 1);
 	
 	private PlayerClass _class;
-	private long _exp = Experience.LEVEL[40];
+	private long _exp = ExperienceTable.getInstance().getExpForLevel(Config.BASE_SUBCLASS_LEVEL);
 	private int _sp = 0;
-	private byte _level = 40;
+	private byte _level = Config.BASE_SUBCLASS_LEVEL;
 	private int _classIndex = 1;
 	
 	public SubClass(int classId, long exp, int sp, byte level, int classIndex)
@@ -96,8 +97,8 @@ public final class SubClass
 	
 	public void setExp(long expValue)
 	{
-		if (expValue > (Experience.LEVEL[_maxLevel + 1] - 1))
-			expValue = (Experience.LEVEL[_maxLevel + 1] - 1);
+		if (expValue > (ExperienceTable.getInstance().getExpForLevel(_maxLevel + 1) - 1))
+			expValue = ExperienceTable.getInstance().getExpForLevel(_maxLevel + 1) - 1;
 		
 		_exp = expValue;
 	}
@@ -116,8 +117,8 @@ public final class SubClass
 	{
 		if (levelValue > _maxLevel)
 			levelValue = _maxLevel;
-		else if (levelValue < 40)
-			levelValue = 40;
+		else if (levelValue < Config.BASE_SUBCLASS_LEVEL)
+			levelValue = Config.BASE_SUBCLASS_LEVEL;
 		
 		_level = levelValue;
 	}
@@ -128,15 +129,15 @@ public final class SubClass
 			return;
 		
 		_level++;
-		setExp(Experience.LEVEL[getLevel()]);
+		setExp(ExperienceTable.getInstance().getExpForLevel(getLevel()));
 	}
 	
 	public void decLevel()
 	{
-		if (getLevel() == 40)
+		if (getLevel() == Config.BASE_SUBCLASS_LEVEL)
 			return;
 		
 		_level--;
-		setExp(Experience.LEVEL[getLevel()]);
+		setExp(ExperienceTable.getInstance().getExpForLevel(getLevel()));
 	}
 }

+ 3 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/CharSelectionInfo.java

@@ -26,10 +26,10 @@ import javolution.util.FastList;
 import com.l2jserver.Config;
 import com.l2jserver.L2DatabaseFactory;
 import com.l2jserver.gameserver.datatables.ClanTable;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.instancemanager.CursedWeaponsManager;
 import com.l2jserver.gameserver.model.CharSelectInfoPackage;
 import com.l2jserver.gameserver.model.L2Clan;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
 import com.l2jserver.gameserver.network.L2GameClient;
 
@@ -128,7 +128,8 @@ public class CharSelectionInfo extends L2GameServerPacket
 			
 			writeD(charInfoPackage.getSp());
 			writeQ(charInfoPackage.getExp());
-			writeF((float)(charInfoPackage.getExp() - Experience.LEVEL[charInfoPackage.getLevel()]) / (Experience.LEVEL[charInfoPackage.getLevel() + 1] - Experience.LEVEL[charInfoPackage.getLevel()])); // High Five exp %
+			writeF((float)(charInfoPackage.getExp() - ExperienceTable.getInstance().getExpForLevel(charInfoPackage.getLevel())) /
+					(ExperienceTable.getInstance().getExpForLevel(charInfoPackage.getLevel() + 1) - ExperienceTable.getInstance().getExpForLevel(charInfoPackage.getLevel()))); // High Five exp %
 			writeD(charInfoPackage.getLevel());
 			
 			writeD(charInfoPackage.getKarma()); // karma

+ 3 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/GMViewCharacterInfo.java

@@ -14,9 +14,9 @@
  */
 package com.l2jserver.gameserver.network.serverpackets;
 
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.model.Elementals;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
 /**
  *
@@ -60,7 +60,8 @@ public class GMViewCharacterInfo extends L2GameServerPacket
 		writeD(_activeChar.getClassId().getId());
 		writeD(_activeChar.getLevel());
 		writeQ(_activeChar.getExp());
-		writeF((float)(_activeChar.getExp() - Experience.LEVEL[_activeChar.getLevel()]) / (Experience.LEVEL[_activeChar.getLevel() + 1] - Experience.LEVEL[_activeChar.getLevel()])); // High Five exp %
+		writeF((float)(_activeChar.getExp() - ExperienceTable.getInstance().getExpForLevel(_activeChar.getLevel())) /
+				(ExperienceTable.getInstance().getExpForLevel(_activeChar.getLevel() + 1) - ExperienceTable.getInstance().getExpForLevel(_activeChar.getLevel()))); // High Five exp %
 		writeD(_activeChar.getSTR());
 		writeD(_activeChar.getDEX());
 		writeD(_activeChar.getCON());

+ 3 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/UserInfo.java

@@ -15,6 +15,7 @@
 package com.l2jserver.gameserver.network.serverpackets;
 
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.NpcTable;
 import com.l2jserver.gameserver.instancemanager.CursedWeaponsManager;
 import com.l2jserver.gameserver.instancemanager.TerritoryWarManager;
@@ -22,7 +23,6 @@ import com.l2jserver.gameserver.model.Elementals;
 import com.l2jserver.gameserver.model.L2Transformation;
 import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
 import com.l2jserver.gameserver.skills.AbnormalEffect;
 import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
@@ -134,7 +134,8 @@ public final class UserInfo extends L2GameServerPacket
 		
 		writeD(_activeChar.getLevel());
 		writeQ(_activeChar.getExp());
-		writeF((float)(_activeChar.getExp() - Experience.LEVEL[_activeChar.getLevel()]) / (Experience.LEVEL[_activeChar.getLevel() + 1] - Experience.LEVEL[_activeChar.getLevel()])); // High Five exp %
+		writeF((float)(_activeChar.getExp() - ExperienceTable.getInstance().getExpForLevel(_activeChar.getLevel())) /
+				(ExperienceTable.getInstance().getExpForLevel(_activeChar.getLevel() + 1) - ExperienceTable.getInstance().getExpForLevel(_activeChar.getLevel()))); // High Five exp %
 		writeD(_activeChar.getSTR());
 		writeD(_activeChar.getDEX());
 		writeD(_activeChar.getCON());

+ 7 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/skills/l2skills/L2SkillSummon.java

@@ -15,6 +15,7 @@
 package com.l2jserver.gameserver.skills.l2skills;
 
 import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.NpcTable;
 import com.l2jserver.gameserver.idfactory.IdFactory;
 import com.l2jserver.gameserver.model.L2Object;
@@ -25,7 +26,6 @@ import com.l2jserver.gameserver.model.actor.instance.L2MerchantSummonInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2SiegeSummonInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2SummonInstance;
-import com.l2jserver.gameserver.model.base.Experience;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
 import com.l2jserver.gameserver.templates.StatsSet;
@@ -232,15 +232,17 @@ public class L2SkillSummon extends L2Skill
 		summon.setName(summonTemplate.name);
 		summon.setTitle(activeChar.getName());
 		summon.setExpPenalty(_expPenalty);
-		if (summon.getLevel() >= Experience.LEVEL.length)
+		
+		if (summon.getLevel() >= ExperienceTable.getInstance().getMaxPetLevel())
 		{
-			summon.getStat().setExp(Experience.LEVEL[Experience.LEVEL.length - 1]);
-			_log.warning("Summon ("+summon.getName()+") NpcID: "+summon.getNpcId()+" has a level above 75. Please rectify.");
+			summon.getStat().setExp(ExperienceTable.getInstance().getExpForLevel(ExperienceTable.getInstance().getMaxPetLevel()-1));
+			_log.warning("Summon (" + summon.getName() + ") NpcID: " + summon.getNpcId() + " has a level above "+ExperienceTable.getInstance().getMaxPetLevel()+". Please rectify.");
 		}
 		else
 		{
-			summon.getStat().setExp(Experience.LEVEL[(summon.getLevel() % Experience.LEVEL.length)]);
+			summon.getStat().setExp(ExperienceTable.getInstance().getExpForLevel(summon.getLevel() % ExperienceTable.getInstance().getMaxPetLevel()));
 		}
+		
 		summon.setCurrentHp(summon.getMaxHp());
 		summon.setCurrentMp(summon.getMaxMp());
 		summon.setHeading(activeChar.getHeading());

+ 3 - 1
L2J_Server_BETA/java/com/l2jserver/loginserver/GameServerTable.java

@@ -14,6 +14,7 @@
  */
 package com.l2jserver.loginserver;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -42,6 +43,7 @@ import javolution.xml.stream.XMLStreamConstants;
 import javolution.xml.stream.XMLStreamException;
 import javolution.xml.stream.XMLStreamReaderImpl;
 
+import com.l2jserver.Config;
 import com.l2jserver.L2DatabaseFactory;
 import com.l2jserver.loginserver.network.gameserverpackets.ServerStatus;
 import com.l2jserver.util.IPSubnet;
@@ -116,7 +118,7 @@ public class GameServerTable
 		InputStream in = null;
 		try
 		{
-			in = new FileInputStream("data/servername.xml");
+			in = new FileInputStream(new File(Config.DATAPACK_ROOT, "data/servername.xml"));
 			XMLStreamReaderImpl xpp = new XMLStreamReaderImpl();
 			xpp.setInput(new UTF8StreamReader().setInput(in));
 			for (int e = xpp.getEventType(); e != XMLStreamConstants.END_DOCUMENT; e = xpp.next())

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/loginserver/mail/MailSystem.java

@@ -61,7 +61,7 @@ public class MailSystem
 		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		factory.setValidating(false);
 		factory.setIgnoringComments(true);
-		File file = new File("data/mail/MailList.xml");
+		File file = new File(Config.DATAPACK_ROOT, "data/mail/MailList.xml");
 		Document doc = null;
 		if (file.exists())
 		{
@@ -85,7 +85,7 @@ public class MailSystem
 					
 					try
 					{
-						FileInputStream fis = new FileInputStream("data/mail/"+maFile);
+						FileInputStream fis = new FileInputStream(new File(Config.DATAPACK_ROOT, "data/mail/"+maFile));
 						BufferedInputStream bis = new BufferedInputStream(fis);
 						int bytes = bis.available();
 						byte[] raw = new byte[bytes];

+ 4 - 0
L2J_Server_BETA/java/config/Character.properties

@@ -291,6 +291,10 @@ MaxDebuffChance = 90
 # Default: 3
 MaxSubclass = 3
 
+# Starting level for subclasses.
+# Default: 40
+BaseSubclassLevel = 40
+
 # Maximum subclass level.
 # Default: 80
 MaxSubclassLevel = 80

+ 1 - 1
L2J_Server_BETA/java/config/email.properties

@@ -22,7 +22,7 @@ ServerInfoAddress = info@myl2jserver.com
 
 # Enable Email System
 # Default: False
-EmailSystemEnabled = True
+EmailSystemEnabled = False
 
 # Mail Server Host
 # Default: smtp.gmail.com

+ 4 - 0
L2J_Server_BETA/java/config/loginserver.properties

@@ -102,6 +102,10 @@ ShowLicence = True
 # Default: True
 AutoCreateAccounts = True
 
+# Datapack root directory.
+# Defaults to current directory from which the server is started unless the below line is uncommented.
+#DatapackRoot = C:/Work/tmp/DataPack
+
 
 # ---------------------------------------------------------------------------
 # Developer Settings